home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1999 June: Reference Library / Dev.CD Jun 99 RL Disk 1.toast / Technical Documentation / Develop / develop Issue 26 / develop Issue 26 code / SOM and ListPart / ListPart DR4 / Source / ListPart.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  1995-12-11  |  116.1 KB  |  3,644 lines  |  [TEXT/MPS ]

  1.  
  2. #if 0
  3.     #define     WeBeHere(StringPtr) DebugStr(StringPtr);
  4. #else
  5.     #define     WeBeHere(StringPtr)
  6. #endif
  7.  
  8. /*------------------------------------------------------------------------------
  9.  
  10.     File:            ListPart.cpp
  11.     
  12.     Written by:        Steve Smith
  13.     
  14.     Copyright:        © 1995 by Apple Computer, Inc., all rights reserved.
  15.     
  16.     Description:    ListPart demonstrates the most basic functions and
  17.                     responsibilities of an OpenDoc™ leaf part.
  18.     
  19.     
  20.     Demonstrates:    The following recipes were used in implementing the
  21.                     ListPart:
  22.                      1. Open
  23.                      2. Adding A Display Frame
  24.                      3. Adding A Facet
  25.                      4. Part Drawing
  26.                      5. Refcounting Geometry
  27.                      6. ViewTypes & Presentations
  28.                      7. Display Frame 'ternalization
  29.                      8. Part Init & Externalization
  30.                      9. Part Init & partWrapper
  31.                     10. Part Storage Model
  32.                     11. Persistent Reference
  33.                     12. RefCounting
  34.                     13. Storage Unit
  35.                     14. Activation
  36.                     15. Basic Event Handling
  37.                     16. Menus
  38.                     17. Windows & Dialogs
  39.                     18. Exception Handling
  40.                     19. Memory Manager
  41.                     20. Using Resources
  42.                     21. Lazy Frame Internalization
  43.                     22. Multiple Kind Support
  44.     
  45.     
  46.     Notes:            • For methods where it is necessary to call the parent class
  47.                     implementation, the calls are made from the SOM class. See
  48.                     som_ListPart.cpp and the Class Reference to know whether
  49.                     you need to call the parent class from any method.                    
  50.     
  51. ------------------------------------------------------------------------------*/
  52.  
  53. // -- Compiler/Preprocessor Switches --
  54.  
  55. #ifndef _COMPILERDEFS_
  56. #include "CompDefs.h"
  57. #endif
  58.  
  59. #ifndef __DEBUGTOOLS__
  60. #include "DebugTools.h"
  61. #endif
  62.  
  63. // -- OpenDoc Utilities --
  64.  
  65. #ifndef _EXCEPT_
  66. // Exceptions define several important macros (eg. CHECKENV)
  67. // which are used in the SOM method dispatch glue. If Except.h
  68. // is not included early enough, exceptions may not be thrown
  69. // correctly when returning from a SOM method with the "ev" parameter set.
  70. #include <Except.h>
  71. #endif
  72.  
  73. // -- ListPart Includes --
  74.  
  75. #ifndef _LISTPARTGLOBALS_
  76. #include "ListPartGlobals.h"
  77. #endif
  78.  
  79. #ifndef _LISTPARTDEF_
  80. #include "ListPartDef.h"
  81. #endif
  82.  
  83. #ifndef _LISTPARTUTILS_
  84. #include "ListPartUtils.h"
  85. #endif
  86.  
  87. #ifndef _LISTPART_
  88. #include "ListPart.h"
  89. #endif
  90.  
  91. #ifndef _SAMPLECOLLECTIONS_
  92. #include "SampleCollections.h"
  93. #endif
  94.  
  95. // -- OpenDoc Includes --
  96.  
  97. #ifndef _ODTYPES_
  98. #include <ODTypes.h>
  99. #endif
  100.  
  101. #ifndef SOM_ODPart_xh
  102. #include <Part.xh>
  103. #endif
  104.  
  105. #ifndef SOM_ODFacet_xh
  106. #include <Facet.xh>
  107. #endif
  108.  
  109. #ifndef SOM_ODFrame_xh
  110. #include <Frame.xh>
  111. #endif
  112.  
  113. #ifndef SOM_ODFrameFacetIterator_xh
  114. #include <FrFaItr.xh>
  115. #endif
  116.  
  117. #ifndef SOM_ODArbitrator_xh
  118. #include <Arbitrat.xh>
  119. #endif
  120.  
  121. #ifndef SOM_Module_OpenDoc_Foci_defined
  122. #include <Foci.xh>
  123. #endif
  124.  
  125. #ifndef SOM_ODShape_xh
  126. #include <Shape.xh>
  127. #endif
  128.  
  129. #ifndef SOM_Module_OpenDoc_StdProps_defined
  130. #include <StdProps.xh>
  131. #endif
  132.  
  133. #ifndef SOM_Module_OpenDoc_StdTypes_defined
  134. #include <StdTypes.xh>
  135. #endif
  136.  
  137. #ifndef SOM_Module_OpenDoc_StdDefs_defined
  138. #include <StdDefs.xh>
  139. #endif
  140.  
  141. #ifndef SOM_Module_OpenDoc_Commands_defined
  142. #include <CmdDefs.xh>
  143. #endif
  144.  
  145. #ifndef SOM_ODDraft_xh
  146. #include <Draft.xh>
  147. #endif
  148.  
  149. #ifndef SOM_ODStorageUnit_xh
  150. #include <StorageU.xh>
  151. #endif
  152.  
  153. #ifndef SOM_ODStorageUnitView_xh
  154. #include <SUView.xh>
  155. #endif
  156.  
  157. #ifndef SOM_ODTransform_xh
  158. #include <Trnsform.xh>
  159. #endif
  160.  
  161. #ifndef SOM_ODFocusSet_xh
  162. #include <FocusSet.xh>
  163. #endif
  164.  
  165. #ifndef SOM_ODMenuBar_xh
  166. #include <MenuBar.xh>
  167. #endif
  168.  
  169. #ifndef SOM_ODWindow_xh
  170. #include <Window.xh>
  171. #endif
  172.  
  173. #ifndef SOM_ODWindowState_xh
  174. #include <WinStat.xh>
  175. #endif
  176.  
  177. #ifndef SOM_ODCanvas_xh
  178. #include <Canvas.xh>
  179. #endif
  180.  
  181. #ifndef SOM_ODSession_xh
  182. #include <ODSessn.xh>
  183. #endif
  184.  
  185. // -- OpenDoc Utilities --
  186.  
  187. #ifndef _ITEXT_
  188. #include <IText.h>
  189. #endif
  190.  
  191. #ifndef _FOCUSLIB_
  192. #include <FocusLib.h>
  193. #endif
  194.  
  195. #ifndef _BNDNSUTL_
  196. #include <BndNSUtl.h>
  197. #endif
  198.  
  199. #ifndef _USERSRCM_
  200. #include <UseRsrcM.h>
  201. #endif
  202.  
  203. #ifndef _ODMEMORY_
  204. #include <ODMemory.h>
  205. #endif
  206.  
  207. #ifndef _ISOSTR_
  208. #include <ISOStr.h>
  209. #endif
  210.  
  211. #ifndef _ODDEBUG_
  212. #include <ODDebug.h>
  213. #endif
  214.  
  215. #ifndef _ODUTILS_
  216. #include <ODUtils.h>
  217. #endif
  218.  
  219. #ifndef _STORUTIL_
  220. #include <StorUtil.h>
  221. #endif
  222.  
  223. #ifndef _STDTYPIO_
  224. #include <StdTypIO.h>
  225. #endif
  226.  
  227. #ifndef _TEMPITER_
  228. #include <TempIter.h>
  229. #endif
  230.  
  231. #ifndef _TEMPOBJ_
  232. #include <TempObj.h>
  233. #endif
  234.  
  235. #ifndef _WINUTILS_
  236. #include <WinUtils.h>
  237. #endif
  238.  
  239. // -- Macintosh Includes --
  240.  
  241. #ifndef __ERRORS__
  242. #include <Errors.h>
  243. #endif
  244.  
  245. #ifndef __RESOURCES__
  246. #include <Resources.h>
  247. #endif
  248.  
  249. #ifndef __DIALOGS__
  250. #include <Dialogs.h>
  251. #endif
  252.  
  253. #ifndef __TOOLUTILS__
  254. #include <ToolUtils.h>
  255. #endif
  256.  
  257. #ifndef __ICONS__
  258. #include <Icons.h>
  259. #endif
  260.  
  261. #ifndef __QUICKDRAW__
  262. #include <Quickdraw.h>
  263. #endif
  264.  
  265. #ifndef __GXMATH__
  266. #include <GXMath.h>
  267. #endif
  268.  
  269. #pragma segment ListPart
  270.  
  271. Environment* gEv;
  272. ODFacet* gFacet;
  273. ControlHandle gControl;
  274. ODPart* gMySelf;
  275. short gInitDelta, gTempoVal;
  276.  
  277. char gTextVersion[71] = "\pListPart (DR 3) v.1.2, © 1995 by Apple Computer France & Éric Simenel";
  278.  
  279. //==============================================================================
  280. // ListPart
  281. //==============================================================================
  282.  
  283. //------------------------------------------------------------------------------
  284. // Method:        Constructor
  285. // Origin:        ListPart
  286. //
  287. // Description:    This is the C++ class constructor.
  288. //
  289. // Warnings:    You are not allowed to throw an exception from this method.
  290. //------------------------------------------------------------------------------
  291.  
  292. ListPart::ListPart()
  293. {
  294.     WeBeHere("\pListPart::ListPart");
  295.     SOM_Trace("ListPart","Constructor");
  296.     
  297.     fDisplayFrames        = kODNULL;
  298.     fDirty                = kODFalse;
  299.     fSelf                = kODNULL;
  300.     fReadOnlyStorage    = kODFalse;
  301.  
  302. // ES 11/15/95
  303.     fThumbnail = kODNULL;
  304.  
  305.     fMul = kODNULL;
  306.     fLineOpened = 0;
  307.     fOpenedFacet = kODNULL;
  308.     fFocusedFacet = kODNULL;
  309.     fGWorld = kODNULL;
  310.     fGWNbLines = 0;
  311.     fLastClickTime = 0;
  312.     fLastClickedLine = -1;
  313.     fDoubleClickedLine = -1;
  314. }
  315.  
  316. //------------------------------------------------------------------------------
  317. // Method:        Destructor
  318. // Origin:        ListPart
  319. //
  320. // Description:    This is the C++ class destructor.
  321. //
  322. // Warnings:    You are not allowed to throw an exception from this method.
  323. //------------------------------------------------------------------------------
  324.  
  325. ListPart::~ListPart()
  326. {
  327.     WeBeHere("\pListPart::~ListPart");
  328.     SOM_Trace("ListPart","Destructor");
  329.  
  330. // ES 11/15/95
  331.     if (fThumbnail) ::KillPicture((PicHandle)fThumbnail);
  332.     if (fGWorld) ::DisposeGWorld(fGWorld);
  333.     if (fMul) ::DisposePtr(fMul);
  334. }
  335.  
  336. //------------------------------------------------------------------------------
  337. // Method:        InitPart
  338. // Origin:        ODPart
  339. //
  340. // Description:    This method is called when a new instance of this part is being
  341. //                created. The part should prepare itself to run.
  342. //
  343. // Parent:        The part's parent class was called before this method was
  344. //                dispatched to (see som_ListPart.cpp).
  345. //
  346. // Warning:        It is not appropriate to require user interaction while
  347. //                stationery is being created. Do not present the user with error
  348. //                dialogs or splash screens from this method.
  349. //------------------------------------------------------------------------------
  350.  
  351. void ListPart::InitPart( Environment*        ev,
  352.                            ODStorageUnit*    storageUnit,
  353.                            ODPart*            partWrapper,
  354.                            ACF_DevServ_som_ListPart* somSelf )
  355. {
  356.     WeBeHere("\pListPart::InitPart");
  357.     SOM_Trace("ListPart","InitPart");
  358.  
  359.     TRY
  360.         // To allow editor swapping (translation) at runtime, OpenDoc requires
  361.         // that we pass in a "reference" to ourselves when interacting with the
  362.         // API (eg. WindowState::RegisterWindow(), Dispatcher::RegisterIdle, etc).
  363.         // The "partWrapper" passed to us here and in InitPartFromStorage is the
  364.         // "reference" OpenDoc is asking us to use.
  365.         fSelf = partWrapper;
  366.     
  367.         // We are being created, either as part of generating stationery or
  368.         // by some editor instantiating the part, so the destination storage
  369.         // must be writeable.
  370.         fReadOnlyStorage = kODFalse;
  371.             
  372.         // Call the common initialization code to get set up.
  373.         this->Initialize(ev, somSelf);
  374.  
  375. // ES 11/13/95
  376.         fsomSelf->InitializeListData(ev, &fNbLines, &fLineHeight, &fLineWidth, &fLineDepth,
  377.                                          &fKind, &fAutoThumb, &fWantKey, &fListIndex, &fSel, &fMul);
  378.         switch (fKind)
  379.             {
  380.             case kPassive:
  381.                 fSel = 0;
  382.             case kMultiple:
  383.                 fSel = -1;
  384.                 break;
  385.             }
  386.         SetUpListParams(ev, storageUnit);
  387.  
  388.         // Since we have just been created, our state/content info has
  389.         // never been written out, so setting our "dirty" flag will
  390.         // give us a chance to do that.
  391.         this->SetDirty(ev);
  392.     
  393.     CATCH_ALL
  394.         // Clean up will occur in the destructor which will be called
  395.         // shortly after we return the error.
  396.         RERAISE;
  397.     ENDTRY
  398. }
  399.  
  400. //------------------------------------------------------------------------------
  401. // Method:        InitPartFromStorage
  402. // Origin:        ODPart
  403. //
  404. // Description:    This method is called when a document/stationery is being opened
  405. //                or when the part is internalized by its containing part. The
  406. //                part should merely read in the saved state/content and
  407. //                initialize itself. The part must not alter its storage unit;
  408. //                otherwise, the "Save" menu item becomes enabled without the user
  409. //                actually having made a change to the document.
  410. //
  411. // Parent:        The part's parent class was called before this method was
  412. //                dispatched to (see som_ListPart.cpp).
  413. //------------------------------------------------------------------------------
  414.  
  415. void ListPart::InitPartFromStorage( Environment*        ev,
  416.                                       ODStorageUnit*    storageUnit,
  417.                                       ODPart*            partWrapper,
  418.                                       ACF_DevServ_som_ListPart* somSelf )
  419. {
  420.     WeBeHere("\pListPart::InitPartFromStorage");
  421.     SOM_Trace("ListPart","InitPartFromStorage");
  422.  
  423.     TRY
  424.         // To allow editor swapping (translation) at runtime, OpenDoc requires
  425.         // that we pass in a "reference" to ourselves when interacting with the
  426.         // API (eg. WindowState::RegisterWindow(), Dispatcher::RegisterIdle, etc).
  427.         // The "partWrapper" passed to us here and in InitPart is the
  428.         // "reference" OpenDoc is asking us to use.
  429.         fSelf = partWrapper;
  430.             
  431.         // Are we being opened from a read-only draft? If so, we cannot
  432.         // write anything back out to our storage unit.
  433.         fReadOnlyStorage = ( ODGetDraft(ev,storageUnit)->
  434.                                 GetPermissions(ev) < kODDPSharedWrite );
  435.             
  436.         // Call the common initialization code to get set up.
  437.         this->Initialize(ev, somSelf);
  438.     
  439.         // Read in the state the part was in when it was last Externalized.
  440.         // This allows the part to present the same "environment" the user
  441.         // had the part set up in the last time it was edited.
  442.         this->InternalizeStateInfo(ev, storageUnit);
  443.     
  444.         // Read in the contents for your part editor.
  445.         this->InternalizeContent(ev, storageUnit);
  446.  
  447.     CATCH_ALL
  448.         // Clean up will occur in the destructor which will be called
  449.         // shortly after we return the error.
  450.         RERAISE;
  451.     ENDTRY
  452. }
  453.  
  454. //------------------------------------------------------------------------------
  455. // Method:        Initialize
  456. // Origin:        ListPart
  457. //
  458. // Description:    This method is called during the initialization of the part. The
  459. //                method is used to initialize all fields of the part and to
  460. //                convert ISO types to tokens for faster comparisons throughout
  461. //                the code.
  462. //
  463. //                If an exception is thrown in this method, it wil be propogated
  464. //                back to OpenDoc which will call our ReleaseAll() method and the
  465. //                class destructor. All memory allocated here will be cleaned up
  466. //                in the ReleaseAll() method.
  467. //------------------------------------------------------------------------------
  468.  
  469. void ListPart::Initialize( Environment*    ev, ACF_DevServ_som_ListPart* somSelf )
  470. {
  471.     WeBeHere("\pListPart::Initialize");
  472.     SOM_Trace("ListPart","Initialize");
  473.  
  474.     // Create a list to keep track of the frames we are being
  475.     // displayed in. Used for part maintenance (ie. Purging memory).
  476.     fDisplayFrames = new CList;
  477.  
  478.     fsomSelf = somSelf;
  479.  
  480.     // First check to see if the library's global variables have
  481.     // been initialized (meaning another part instantiation is already
  482.     // running).
  483.  
  484.     if ( gGlobalsUsageCount == 0 )
  485.     {
  486.         // Grab a reference to the Session object. This is merely for
  487.         // convenience.
  488.         ODSession* session = ODGetSession(ev,fSelf);
  489.             
  490.         // Create our globals space. We store the globals in a struct so
  491.         // that we can put them in temp mem. Otherwise, CFM loads the globals
  492.         // with the data fragment of a CFM library in the application heap.
  493.         gGlobals = new ListPartGlobals;
  494.     
  495.         // It is required that parts instantiate their menu bars from 
  496.         // the base OpenDoc menu bar. This maintains consistency in the
  497.         // default menu items and their placement.
  498.         // Since the object is a copy, we can add and subtract menus and
  499.         // items without affecting other running parts.
  500.         gGlobals->fMenuBar = session->GetWindowState(ev)->CopyBaseMenuBar(ev);
  501.  
  502.         // We will be using the following foci (shared resources) in this
  503.         // part. For convenience, we tokenize the values here and store
  504.         // them for equivalence tests in the activation methods.
  505.         gGlobals->fSelectionFocus = session->Tokenize(ev, kODSelectionFocus);
  506.         gGlobals->fMenuFocus = session->Tokenize(ev, kODMenuFocus);
  507.         gGlobals->fModalFocus = session->Tokenize(ev, kODModalFocus);
  508.         gGlobals->fKeyFocus = session->Tokenize(ev, kODKeyFocus);
  509.         gGlobals->fScrollFocus = session->Tokenize(ev, kODScrollingFocus);
  510.     
  511.         // Also for convenience, we tokenize our part's main presentation
  512.         // and the standard view types.
  513.         gGlobals->fMainPresentation = session->Tokenize(ev, kMainPresentation);
  514.     
  515.         gGlobals->fFrameView = session->Tokenize(ev, kODViewAsFrame);
  516.         gGlobals->fLargeIconView = session->Tokenize(ev, kODViewAsLargeIcon);
  517.         gGlobals->fSmallIconView = session->Tokenize(ev, kODViewAsSmallIcon);
  518.         gGlobals->fThumbnailView = session->Tokenize(ev, kODViewAsThumbnail);
  519.     
  520.         // Lastly, we will package the menu and selection focus
  521.         // so that we can request the "set" at activation time.
  522.         gGlobals->fUIFocusSet = session->GetArbitrator(ev)->CreateFocusSet(ev);
  523.         gGlobals->fUIFocusSet->Add(ev, gGlobals->fKeyFocus);
  524.         gGlobals->fUIFocusSet->Add(ev, gGlobals->fMenuFocus);
  525.         gGlobals->fUIFocusSet->Add(ev, gGlobals->fSelectionFocus);
  526.         gGlobals->fUIFocusSet->Add(ev, gGlobals->fScrollFocus);
  527.             
  528.         // Determine what Script/Language the part is localized for.
  529.         // This is important/necessary for creating OpenDoc's text objects.
  530.         GetEditorScriptLanguage(ev, fsomSelf, &gGlobals->fEditorsScript, &gGlobals->fEditorsLanguage);
  531.         
  532.         // The first client of the global variables is running.
  533.         gGlobalsUsageCount = 1;
  534.     }
  535.     else
  536.     // If the globals have been initialized, we just bump the "usage" count so
  537.     // that we know how many part instances are using them.
  538.     {
  539.         gGlobalsUsageCount++;
  540.     }
  541. }
  542.  
  543. //------------------------------------------------------------------------------
  544. // Method:        Release
  545. // Origin:        ODPart
  546. //
  547. // Description:    This method is called each time an object releases a reference
  548. //                to the part. If the refcount falls to 0, the part should
  549. //                release the fSelf part reference.
  550. //
  551. // Parent:        The part's parent class was called before this method was
  552. //                dispatched to (see som_ListPart.cpp).
  553. //
  554. // Warning:        If the part releases any other object when the refcount falls to
  555. //                zero, it will need to override the Acquire method so
  556. //                that the object can be referenced again if the parts refcount
  557. //                should be incremented before it is deleted.
  558. //------------------------------------------------------------------------------
  559.  
  560. void ListPart::Release( Environment* ev )
  561. {
  562.     WeBeHere("\pListPart::Release");
  563.     SOM_Trace("ListPart","Release");
  564.  
  565.     if ( fSelf->GetRefCount(ev) == 0 )
  566.         ODGetDraft(ev,fSelf)->ReleasePart(ev,fSelf);
  567. }
  568.  
  569. //------------------------------------------------------------------------------
  570. // Method:        ReleaseAll
  571. // Origin:        ODPart
  572. //
  573. // Description:    This method is called just prior to the part being deleted by
  574. //                the Draft. The part must release all references to all
  575. //                refcounted objects it has stored internally; not doing so, will
  576. //                cause an "invalid ref count" exception/error at some later time.
  577. //
  578. // Parent:        The part's parent class will be called after this method
  579. //                returns (see som_ListPart.cpp).
  580. //------------------------------------------------------------------------------
  581.  
  582. void ListPart::ReleaseAll( Environment* ev )
  583. {
  584.     WeBeHere("\pListPart::ReleaseAll");
  585.     SOM_Trace("ListPart","ReleaseAll");
  586.  
  587.     TRY
  588.         // If the last part instance using the globals is released,
  589.         // we need to clean up and delete the globals.
  590.         
  591.         if ( --gGlobalsUsageCount == 0 )
  592.         {
  593.             // Release the menubar.
  594.             ODReleaseObject(ev, gGlobals->fMenuBar);
  595.             
  596.             // But first, we need to delete the objects we created
  597.             // and stored in the globals struct.
  598.             ODDeleteObject(gGlobals->fUIFocusSet);
  599.  
  600.             // Now, clean up the globals struct.
  601.             ODDeleteObject(gGlobals);
  602.         }
  603.     
  604.         // Remove and release our display frames.
  605.         if ( fDisplayFrames )
  606.         {
  607.             CListIterator fiter(fDisplayFrames);
  608.             for ( CFrameProxy* proxy = (CFrameProxy*) fiter.First();
  609.                     fiter.IsNotComplete(); proxy = (CFrameProxy*) fiter.Next() )
  610.             {
  611.                 // Delete the proxy object and its contents. The frame's
  612.                 // refcount will be decremented in the proxy destructor.
  613.                 fiter.RemoveCurrent();
  614.                 delete proxy;
  615.             }
  616.         
  617.             // Delete the display frame collection.
  618.             ODDeleteObject(fDisplayFrames);
  619.         }
  620.         
  621.     CATCH_ALL
  622.         // If something goes wrong while we are cleaning up, we must
  623.         // let the Draft now because there may be some refcounted objects
  624.         // which did not get released. Not to mention, possible memory
  625.         // leaks.
  626.         RERAISE;            
  627.     ENDTRY
  628. }
  629.  
  630. //------------------------------------------------------------------------------
  631. // Method:        Purge
  632. // Origin:        ODPart
  633. //
  634. // Description:    This method is called when the OpenDoc requires more memory for
  635. //                allocating objects and just before a part is deleted. The part
  636. //                should free up as much memory as it can.
  637. //
  638. //                The part determines which views are being "used" in its display
  639. //                frames. The resources for the unused view types are then purged.
  640. //------------------------------------------------------------------------------
  641.  
  642. ODSize ListPart::Purge( Environment*    ev,
  643.                           ODSize        /*size*/ )
  644. {
  645.     WeBeHere("\pListPart::Purge");
  646.     SOM_Trace("ListPart","Purge");
  647.  
  648.     // Purge is called during the creation of stationery. However,
  649.     // we have not created our internal display frames list, so 
  650.     // trying to iterate over it would be fatal.
  651.     if ( fDisplayFrames == kODNULL ) return 0;
  652.     
  653.     ODSize         bytesFreed        = 0;
  654.     ODBoolean    usingThumbnail  = kODFalse;
  655.     
  656.     // Iterate over the frames we are displayed through and determine which
  657.     // view types are currently in use.
  658.     
  659.     CListIterator fiter(fDisplayFrames);
  660.     for ( CFrameProxy* proxy = (CFrameProxy*) fiter.First();
  661.             fiter.IsNotComplete(); proxy = (CFrameProxy*) fiter.Next() )
  662.     {
  663.         // If the display frame is real (has been "connected" or was "added")
  664.         // get its view type; otherwise, ignore it.
  665.         if ( proxy->FrameIsLoaded() )
  666.         {
  667.             ODTypeToken    frameView = proxy->GetFrame(ev)->GetViewType(ev);
  668.             
  669.             if ( frameView == gGlobals->fThumbnailView )
  670.                 usingThumbnail = kODTrue;
  671.             
  672.             // Release the frame reference, but don't get rid of the
  673.             // proxy object because we're not done with the frame. If
  674.             // all parts release their references the frame will be
  675.             // purged from memory.
  676.             proxy->Purge(ev);
  677.         }
  678.     }
  679.     
  680.     // Based on the usage of the supported view types, free up as much
  681.     // memory as possible.
  682. /*
  683.     if ( !usingThumbnail && (fThumbnail != kODNULL) )
  684.     {
  685.         bytesFreed += (ODSize) ODGetHandleSize(fThumbnail);
  686.         ReleaseResource(fThumbnail);
  687.         fThumbnail = kODNULL;
  688.     }
  689. */
  690.     return bytesFreed;
  691. }
  692.  
  693. //------------------------------------------------------------------------------
  694. // Method:        InternalizeStateInfo
  695. // Origin:        ListPart
  696. //
  697. // Description:    This method is used to read in "state" information for the part.
  698. //                This is information related to the workings of the part editor,
  699. //                not the content.
  700. //
  701. //                The part writes out a list of weak references to its display
  702. //                frames. This allows the part to reuse the same display frames
  703. //                each time the document is opened. Those references are read
  704. //                back in and validated here.
  705. //
  706. // Note:        The function StorageUnitGetValue simplifies the use of
  707. //                ODByteArrary, which is required the StorageUnit interface. Look
  708. //                in StorUtil.h/cpp for an example of using the ODByteArray struct.
  709. //------------------------------------------------------------------------------
  710.  
  711. void ListPart::InternalizeStateInfo( Environment*        ev,
  712.                                        ODStorageUnit*    storageUnit )
  713. {
  714.     SOM_Trace("ListPart","InternalizeStateInfo");
  715.  
  716.     ODStorageUnitRef    weakRef;
  717.     ODULong                size;
  718.  
  719.     // Internalize the part's display frame list.
  720.  
  721.     if ( storageUnit->Exists(ev, kODPropDisplayFrames, kODWeakStorageUnitRefs, 0) )
  722.     {
  723.         storageUnit->Focus(ev, kODPropDisplayFrames, kODPosUndefined,
  724.                                     kODWeakStorageUnitRefs, 0, kODPosUndefined);
  725.                                     
  726.         size = storageUnit->GetSize(ev);
  727.         storageUnit->SetOffset(ev, 0);    
  728.     
  729.         for ( ODULong offset = 0; offset < size; offset += kODStorageUnitRefSize )
  730.         {    
  731.             TRY    
  732.                 StorageUnitGetValue(storageUnit, ev, kODStorageUnitRefSize, (ODPtr)&weakRef);
  733.                 
  734.                 if ( storageUnit->IsValidStorageUnitRef(ev, weakRef) )
  735.                 {        
  736.                     // We lazily internalize our display frames, meaning we don't "get"
  737.                     // the frame until we absolutely need it. This reduces the time
  738.                     // to internalize the part and the amount of memory needed.
  739.                     
  740.                     // Convert the reference into a runtime id.
  741.                     ODID frameID = storageUnit->GetIDFromStorageUnitRef(ev, weakRef);
  742.  
  743.                     // Create a proxy class to support the lazy internalization.
  744.                     CFrameProxy* proxy = new CFrameProxy;
  745.                     proxy->InitFrameProxy(frameID, ODGetDraft(ev,storageUnit));
  746.  
  747.                     // Add the proxy to the display frame collection.
  748.                     fDisplayFrames->Add(proxy);
  749.                 }
  750.             CATCH_ALL
  751.                 // consume exception
  752.             ENDTRY
  753.         }
  754.     }
  755. }
  756.  
  757. //------------------------------------------------------------------------------
  758. // Method:        InternalizeContent
  759. // Origin:        ListPart
  760. //
  761. // Description:    This method is called during initialization of the part from an
  762. //                existing document. The content of the part should be read in.
  763. //
  764. //                The part has no intrinsic content, so the part does nothing.
  765. //                The method is here for completeness.
  766. //------------------------------------------------------------------------------
  767.  
  768. void ListPart::InternalizeContent( Environment*        ev,
  769.                                      ODStorageUnit*        storageUnit )
  770. {
  771.     WeBeHere("\pListPart::InternalizeContent");
  772.     SOM_Trace("ListPart","InternalizeContent");
  773.     
  774. // ES 11/13/95
  775.     if (ODSUExistsThenFocus(ev, storageUnit, kODPropContents, fsomSelf->GetTheRealPartKind(ev)))
  776.     {
  777.     Str255 version;
  778.     version[0] = (unsigned char)storageUnit->GetSize(ev);
  779.     StorageUnitGetValue(storageUnit, ev, version[0], &version[1]);
  780.     }
  781.  
  782.     InternalizeListParams(ev, storageUnit);
  783.  
  784. }
  785.  
  786. //------------------------------------------------------------------------------
  787. // Method:        CloneInto
  788. // Origin:        ODPart
  789. //
  790. // Description:    This method is called during cloning, typically during data
  791. //                interchange operations (eg. Cut/Paste). The part should
  792. //                write out its current state and content.
  793. //
  794. // Parent:        The part's parent class was called before this method was
  795. //                dispatched to (see som_ListPart.cpp).
  796. //------------------------------------------------------------------------------
  797.  
  798. void ListPart::CloneInto( Environment*        ev,
  799.                             ODDraftKey            key,
  800.                             ODStorageUnit*        destinationSU,
  801.                             ODFrame*            initiatingFrame )
  802. {
  803.     WeBeHere("\pListPart::CloneInto");
  804.     SOM_Trace("ListPart","CloneInto");
  805.     
  806.     // We must first verify that we've never written to this storage unit.
  807.     // If we have, we should do nothing, otherwise we need to write out
  808.     // the current state of the part content.
  809.     
  810.     if ( destinationSU->Exists(ev, kODPropContents, fsomSelf->GetTheRealPartKind(ev), 0) == kODFalse )
  811.     {
  812.         // Add the properties we need to successfully externalize
  813.         // ourselves into the destination storage unit.
  814.         this->CheckAndAddProperties(ev, destinationSU);
  815.                 
  816.         // Write out the part's state information.
  817.         this->ExternalizeStateInfo(ev, destinationSU, key, initiatingFrame);
  818.             
  819.         // Write out the part's content.
  820.         this->ExternalizeContent(ev, destinationSU, key, initiatingFrame);
  821.     }
  822. }
  823.  
  824. //------------------------------------------------------------------------------
  825. // Method:        Externalize
  826. // Origin:        ODPart
  827. //
  828. // Description:    This method is called when the user saves the document. The part
  829. //                should write out its state and content if changes have occurred
  830. //                and if our storage is writeable.
  831. //
  832. // Parent:        The part's parent class was called before this method was
  833. //                dispatched to (see som_ListPart.cpp).
  834. //------------------------------------------------------------------------------
  835.  
  836. void ListPart::Externalize( Environment* ev )
  837. {
  838.     WeBeHere("\pListPart::Externalize");
  839.     SOM_Trace("ListPart","Externalize");
  840.  
  841.     TRY
  842.         if ( fDirty && !fReadOnlyStorage )
  843.         {
  844.             // Get our storage unit.
  845.             ODStorageUnit* storageUnit = fSelf->GetStorageUnit(ev);
  846.         
  847.             // Verify that the storage unit has the appropriate properties
  848.             // and values to allow us to run. If not, add them.
  849.             this->CheckAndAddProperties(ev, storageUnit);
  850.         
  851.             // Verify that there are no "bogus" values in the Content
  852.             // property.
  853.             this->CleanseContentProperty(ev, storageUnit);
  854.         
  855.             // Write out the part's state information.
  856.             this->ExternalizeStateInfo(ev, storageUnit, kODNULLKey, kODNULL);
  857.                 
  858.             // Write out the part's content.
  859.             this->ExternalizeContent(ev, storageUnit, kODNULLKey, kODNULL);
  860.     
  861.             // Flag our part as no longer being dirty.
  862.             fDirty = kODFalse;
  863.         }
  864.     CATCH_ALL
  865.         // Alert the user of the problem.
  866.         this->DoDialogBox(ev, kODNULL, kErrorBoxID, kErrExternalizeFailed);
  867.         // Change the exception value, so the DocShell doesn't display an
  868.         // error dialog.
  869.         SetErrorCode(kODErrAlreadyNotified);
  870.         // Alert the caller.
  871.         RERAISE;
  872.     ENDTRY
  873. }
  874.  
  875. //------------------------------------------------------------------------------
  876. // Method:        ExternalizeKinds
  877. // Origin:        ODPart
  878. //
  879. // Description:    This method is called when the user wants to save the document
  880. //                with multiple representations of the data. This is especially
  881. //                useful for increasing the portability of documents
  882. //                cross-platform.
  883. //
  884. //                A part should verify each kind is valid, that it exists in
  885. //                the content property in the correct order, and write the data.
  886. //
  887. // Note:        For parts which support only on kind, the code can simplified.
  888. //                In this case, it is not necessary to iterate over the kindset
  889. //                because you must, at least, write your preferred kind. The code
  890. //                is shown this way to better illustrate the recipe; it is not
  891. //                wrong, it just does more than it needs to.
  892. //------------------------------------------------------------------------------
  893.  
  894. void ListPart::ExternalizeKinds(Environment* ev, ODTypeList* kindset)
  895. {
  896.     if ( !fReadOnlyStorage )
  897.     {
  898.         ODBoolean preferredKindWritten = kODFalse;
  899.         
  900.         // Get our storage unit.
  901.         ODStorageUnit* storageUnit = fSelf->GetStorageUnit(ev);
  902.         
  903.         // Verify that the storage unit has the appropriate properties
  904.         // and values to allow us to run. If not, add them.
  905.         this->CheckAndAddProperties(ev, storageUnit);
  906.     
  907.         // Verify that there are no "bogus" values in the Content
  908.         // property.
  909.         this->CleanseContentProperty(ev, storageUnit);
  910.     
  911.         // Iterate over the kindset and write out the content types
  912.         // that we support.
  913.         TempODTypeListIterator tliter(ev, kindset);
  914.         for ( ODType kind = tliter.First(); tliter.IsNotComplete();
  915.                 kind = tliter.Next() )
  916.         {
  917.             // Check to see if this is a kind we support. If so, write it.
  918.             if ( ODISOStrCompare(kind, fsomSelf->GetTheRealPartKind(ev)) == 0 )
  919.             {
  920.                 // Write out the part's content.
  921.                 this->ExternalizeContent(ev, storageUnit, kODNULLKey, kODNULL);
  922.                 // This is our preferrend kind so we don't need to write it again.
  923.                 // Part editors with more than one kind need to test each kind
  924.                 // against the preferred kind to make sure it's been written.
  925.                 preferredKindWritten = kODTrue;
  926.             }
  927.         }
  928.     
  929.         // Write out the part's state information.
  930.         this->ExternalizeStateInfo(ev, storageUnit, kODNULLKey, kODNULL);
  931.  
  932.         // Even if the kind set contains no types we support, we must at least
  933.         // write out our current "preferred" kind.
  934.         if ( preferredKindWritten == kODFalse )
  935.         {
  936.             // Write out the part's preferred content kind, which, for ListPart,
  937.             // is the only kind.
  938.             this->ExternalizeContent(ev, storageUnit, kODNULLKey, kODNULL);
  939.         }
  940.     }
  941. }
  942.  
  943. //------------------------------------------------------------------------------
  944. // Method:        ChangeKind
  945. // Origin:        ODPart
  946. //
  947. // Description:    This method is called when the changes the part's primary kind
  948. //                and/or when the part editor is switched via the Info dialog.
  949. //
  950. //                The editor should record the new "preferred" kind and change the
  951. //                UI, if necessary, to allow editing of that kind. Don't write the
  952. //                properties/values/data until the Externalize is called.
  953. //------------------------------------------------------------------------------
  954.  
  955. void ListPart::ChangeKind(Environment* ev, ODType kind)
  956. {
  957.     // ListPart only has one kind, but we need to make sure the "Preferred Kind"
  958.     // property has the correct value.
  959.     if ( ODISOStrCompare(kind, fsomSelf->GetTheRealPartKind(ev)) == 0 )
  960.     {
  961.         // Get our storage unit.
  962.         ODStorageUnit* storageUnit = fSelf->GetStorageUnit(ev);
  963.         
  964.         TRY
  965.             // Write out the users preferred kind.
  966.             ODSetISOStrProp(ev, storageUnit, kODPropPreferredKind, kODISOStr, fsomSelf->GetTheRealPartKind(ev));
  967.             
  968.             // Changing our kind dirties our content.
  969.             this->SetDirty(ev);
  970.             
  971.             // Immediately externalize ourselves in the "new" format.
  972.             this->Externalize(ev);
  973.         CATCH_ALL
  974.             // Remove the property and value if something went wrong.
  975.             ODSURemoveProperty(ev, storageUnit, kODPropPreferredKind);
  976.         ENDTRY
  977.     }
  978.     else
  979.         THROW(kODErrInvalidValueType);
  980. }
  981.  
  982. //------------------------------------------------------------------------------
  983. // Method:        ExternalizeStateInfo
  984. // Origin:        ListPart
  985. //
  986. // Description:    This method is called during externalization of the part. The
  987. //                current "state" of the part should be written out. This "state"
  988. //                information may be lost during Data Interchange operations, so
  989. //                the part needs to recover gracefully if information is missing
  990. //                or incomplete.
  991. //
  992. // Note:        The function StorageUnitSetValue is a macro which simplifies
  993. //                the use of ODByteArrary, which is required by the StorageUnit
  994. //                interface. Look in StorUtil.h/cpp for an example of using the
  995. //                ODByteArray struct.
  996. //------------------------------------------------------------------------------
  997.  
  998. void ListPart::ExternalizeStateInfo( Environment*        ev,
  999.                                        ODStorageUnit*    storageUnit,
  1000.                                        ODDraftKey        key,
  1001.                                        ODFrame*            scopeFrame )
  1002. {
  1003.     SOM_Trace("ListPart","ExternalizeStateInfo");
  1004.  
  1005.     ODStorageUnitRef    weakRef;
  1006.     ODID                frameID;
  1007.     ODID                scopeFrameID = ( scopeFrame ? scopeFrame->GetID(ev) : kODNULLID );
  1008.     ODDraft*            fromDraft = ODGetDraft(ev,fSelf);
  1009.     
  1010.     // Externalize the part's display frame list.
  1011.  
  1012.     storageUnit->Focus(ev, kODPropDisplayFrames, kODPosUndefined,
  1013.                                 kODWeakStorageUnitRefs, 0, kODPosUndefined);
  1014.     
  1015.     // Persistent object references are stored in a side table, rather than
  1016.     // in the property/value stream. Thus, deleting the contents of a value
  1017.     // will not "delete" the references previously written to that value. To
  1018.     // completely "delete" all references written to the value, we must
  1019.     // remove the value and add it back.
  1020.     storageUnit->Remove(ev);
  1021.     storageUnit->AddValue(ev, kODWeakStorageUnitRefs);
  1022.  
  1023.     CListIterator fiter(fDisplayFrames);
  1024.     for ( CFrameProxy* proxy = (CFrameProxy*) fiter.First();
  1025.             fiter.IsNotComplete(); proxy = (CFrameProxy*) fiter.Next() )
  1026.     {
  1027.         // Get the ID of the frame we are going to weakly reference.
  1028.         frameID = proxy->GetID();
  1029.         
  1030.         // If a draft key exists, then we are being cloned to another draft.
  1031.         // We must "weak" clone our display frame and reference the cloned
  1032.         // frame. The part re-uses the frameID variable so there aren't two
  1033.         // different GetWeakStorageUnitRef calls.
  1034.         if ( key )
  1035.             frameID = fromDraft->WeakClone(ev, key, frameID, kODNULLID, scopeFrameID);
  1036.         
  1037.         // Write out weak references to each of the part's display frames.
  1038.         storageUnit->GetWeakStorageUnitRef(ev, frameID, weakRef);
  1039.         TRY
  1040.             StorageUnitSetValue(storageUnit, ev, kODStorageUnitRefSize, (ODPtr)&weakRef);
  1041.         CATCH_ALL
  1042.             // consume the exception
  1043.         ENDTRY
  1044.     }
  1045. }
  1046.  
  1047. //------------------------------------------------------------------------------
  1048. // Method:        ExternalizeContent
  1049. // Origin:        ListPart
  1050. //
  1051. // Description:    This method is called during exteralization of the part. The
  1052. //                content of the part should be written out.
  1053. //
  1054. //                The part has no intrinsic content, so the part does nothing.
  1055. //                The method is here for completeness.
  1056. //------------------------------------------------------------------------------
  1057.  
  1058. void ListPart::ExternalizeContent( Environment*        ev,
  1059.                                      ODStorageUnit*        storageUnit,
  1060.                                      ODDraftKey            /*key*/,
  1061.                                      ODFrame*            /*scopeFrame*/ )
  1062. {
  1063.     WeBeHere("\pListPart::ExternalizeContent");
  1064.     SOM_Trace("ListPart","ExternalizeContent");
  1065.  
  1066.     // You would write out your part's content after focusing to your
  1067.     // content property.
  1068.  
  1069. // ES 11/13/95
  1070.     ODSUForceFocus(ev, storageUnit, kODPropContents, fsomSelf->GetTheRealPartKind(ev));
  1071.     ODULong    oldSize = storageUnit->GetSize(ev);
  1072.         // Focus on content property, get size of the old data in there.
  1073.         
  1074.     StorageUnitSetValue(storageUnit, ev, gTextVersion[0], &gTextVersion[1]);
  1075.         // Now we write out the property.
  1076.         
  1077.     ODULong newSize = storageUnit->GetOffset(ev);
  1078.     if (newSize < oldSize)
  1079.         storageUnit->DeleteValue(ev, oldSize - newSize);
  1080.  
  1081. // ES 11/13/95
  1082.     ExternalizeListParams(ev, storageUnit);
  1083.  
  1084. }
  1085.  
  1086. //------------------------------------------------------------------------------
  1087. // Method:        CleanseContentProperty
  1088. // Origin:        ListPart
  1089. //
  1090. // Description:    This method is called during exteralization of the part so that
  1091. //                the part can remove any value in the content property
  1092. //                that it cannot "accurately" write to.
  1093. //
  1094. // Note:        "Additional" values will be added to a part's content property
  1095. //                during Drag & Drop operations.
  1096. //------------------------------------------------------------------------------
  1097.  
  1098. void ListPart::CleanseContentProperty( Environment*        ev,
  1099.                                          ODStorageUnit*        storageUnit )
  1100. {
  1101.     SOM_Trace("ListPart","CleanseContentProperty");
  1102.  
  1103.     ODULong numValues;
  1104.     ODULong index;
  1105.     
  1106.     storageUnit->Focus(ev, kODPropContents, kODPosUndefined, 
  1107.                             kODNULL, 0, kODPosAll);
  1108.     
  1109.     numValues = storageUnit->CountValues(ev);
  1110.     
  1111.     for (index = numValues; index >= 1; index--)
  1112.     {
  1113.         // Index from 1 to n through the values.
  1114.         storageUnit->Focus(ev, kODPropContents, kODPosUndefined, 
  1115.                                 kODNULL, index, kODPosUndefined);
  1116.                                 
  1117.         // Get the ISO type name for the value. The temp object
  1118.         // will automatically delete the returned value when this
  1119.         // scope is exited.
  1120.         TempODValueType value = storageUnit->GetType(ev);
  1121.         
  1122.         // If the value type is not one we support, remove it.
  1123.         if ( ODISOStrCompare(value, fsomSelf->GetTheRealPartKind(ev)) != 0 )
  1124.             storageUnit->Remove(ev);
  1125.     }
  1126. }
  1127.  
  1128. //------------------------------------------------------------------------------
  1129. // Method:        CheckAndAddProperties
  1130. // Origin:        ListPart
  1131. //
  1132. // Description:    This method is called during externalization of the part to
  1133. //                verify that all the properties needed to persistently represent
  1134. //                the current running state of the part.
  1135. //
  1136. //                The part adds the default content property, a preferred editor
  1137. //                property (to aid in part binding), and a display frames
  1138. //                property.
  1139. //
  1140. // Note:        The function StorageUnitSetValue is a macro which simplifies
  1141. //                the use of ODByteArrary, which is required the StorageUnit
  1142. //                interface. Look in StorUtil.h/cpp for an example of using the
  1143. //                ODByteArray struct.
  1144. //------------------------------------------------------------------------------
  1145.  
  1146. void ListPart::CheckAndAddProperties( Environment*    ev,
  1147.                                         ODStorageUnit*    storageUnit )
  1148. {
  1149.     SOM_Trace("ListPart","CheckAndAddProperties");
  1150.  
  1151.     // Create our content property and preferred content property kind.
  1152.  
  1153.     if ( !storageUnit->Exists(ev, kODPropContents, kODNULL, 0) )
  1154.         storageUnit->AddProperty(ev, kODPropContents);
  1155.     if ( !storageUnit->Exists(ev, kODPropContents, fsomSelf->GetTheRealPartKind(ev), 0) )
  1156.     {    
  1157.         storageUnit->Focus(ev, kODPropContents, kODPosUndefined, kODNULL, 0, kODPosAll);
  1158.         storageUnit->AddValue(ev, fsomSelf->GetTheRealPartKind(ev));
  1159.     }
  1160.  
  1161.     // Since we are setting up the preferred kind property, we just write
  1162.     // out our default "kind" for the editor. We can write out the user
  1163.     // chosen kind in the ExternalizeStateInfo method.
  1164.  
  1165.     if ( !storageUnit->Exists(ev, kODPropPreferredKind, kODISOStr, 0) )
  1166.     {
  1167.         TRY
  1168.             ODSetISOStrProp(ev, storageUnit, kODPropPreferredKind, kODISOStr, fsomSelf->GetTheRealPartKind(ev));
  1169.         CATCH_ALL
  1170.             // Remove the property and value if something went wrong.
  1171.             ODSURemoveProperty(ev, storageUnit, kODPropPreferredKind);
  1172.         ENDTRY
  1173.     }
  1174.         
  1175.     // Add our display frame list.
  1176.     
  1177.     if ( !storageUnit->Exists(ev, kODPropDisplayFrames, kODNULL, 0) )
  1178.         storageUnit->AddProperty(ev, kODPropDisplayFrames);
  1179.     if ( !storageUnit->Exists(ev, kODPropDisplayFrames, kODWeakStorageUnitRefs, 0) )
  1180.     {
  1181.         storageUnit->Focus(ev, kODPropDisplayFrames, kODPosUndefined, kODNULL, 0, kODPosAll);
  1182.         storageUnit->AddValue(ev, kODWeakStorageUnitRefs);
  1183.     }
  1184. }
  1185.  
  1186. //------------------------------------------------------------------------------
  1187. // Method:        SetDirty
  1188. // Origin:        ListPart
  1189. //
  1190. // Description:    This method is called by the part when the content or state of
  1191. //                the part has been modified by the user and the "Save" menu item
  1192. //                should be enabled.
  1193. //------------------------------------------------------------------------------
  1194.  
  1195. void ListPart::SetDirty( Environment*    ev )
  1196. {
  1197.     WeBeHere("\pListPart::SetDirty");
  1198.     SOM_Trace("ListPart","SetDirty");
  1199.  
  1200.     // There is no need to repeatedly tell the draft we have changed;
  1201.     // once is sufficient.
  1202.     if ( !fDirty && !fReadOnlyStorage )
  1203.     {
  1204.         fDirty = kODTrue;
  1205.         ODGetDraft(ev,fSelf)->SetChangedFromPrev(ev);
  1206.     }
  1207. }
  1208.  
  1209. //------------------------------------------------------------------------------
  1210. // Method:        ReadPartInfo
  1211. // Origin:        ODPart
  1212. //
  1213. // Description:    When a frame is being internalized by the Draft, it will ask the
  1214. //                owner (part) to read in its info annotation on the frame.
  1215. //
  1216. //                The part uses a C++ helper class to encapsulate the information
  1217. //                we store with each frame, so we let it internalize itself from
  1218. //                the storage unit view.
  1219. //------------------------------------------------------------------------------
  1220.  
  1221. ODInfoType ListPart::ReadPartInfo( Environment*        ev,
  1222.                                      ODFrame*            frame,
  1223.                                      ODStorageUnitView*    storageUnitView )
  1224. {
  1225.     SOM_Trace("ListPart","ReadPartInfo");
  1226.  
  1227.     CFrameInfo* frameInfo = new CFrameInfo(ODGetSession(ev,fSelf));
  1228.         
  1229.     TRY
  1230.         // Ask the info class to internalize itself.
  1231.         frameInfo->InitFromStorage(ev, storageUnitView);
  1232.     CATCH_ALL
  1233.         // Clean up the allocated memory.
  1234.         ODDeleteObject(frameInfo);
  1235.         // Alert the caller.
  1236.         RERAISE;
  1237.     ENDTRY
  1238.     
  1239.     return (ODInfoType)frameInfo;
  1240. }
  1241.  
  1242. //------------------------------------------------------------------------------
  1243. // Method:        WritePartInfo
  1244. // Origin:        ODPart
  1245. //
  1246. // Description:    When a frame is being externalized by the Draft, it will ask the
  1247. //                owner (part) to write out its info annotation on the frame.
  1248. //
  1249. //                The part uses a C++ helper class to encapsulate the information
  1250. //                we store with each frame, so we let it externalize itself to
  1251. //                the storage unit view.
  1252. //------------------------------------------------------------------------------
  1253.  
  1254. void ListPart::WritePartInfo( Environment*        ev,
  1255.                                   ODInfoType            partInfo,
  1256.                                 ODStorageUnitView*    storageUnitView )
  1257. {
  1258.     SOM_Trace("ListPart","WritePartInfo");
  1259.     
  1260.     // Tell our frame info class to write itself out into the pre-
  1261.     // focused storage unit.
  1262.     ((CFrameInfo*) partInfo)->Externalize(ev, storageUnitView);
  1263. }
  1264.  
  1265. //------------------------------------------------------------------------------
  1266. // Method:        ClonePartInfo
  1267. // Origin:        ODPart
  1268. //
  1269. // Description:    When a frame is being cloned by the Draft, it will ask the owner
  1270. //                (part) to clone its info annotation on the frame.
  1271. //
  1272. //                The part uses a C++ helper class to encapsulate the information
  1273. //                we store with each frame, so we let it clone itself to the
  1274. //                storage unit view.
  1275. //------------------------------------------------------------------------------
  1276.  
  1277. void ListPart::ClonePartInfo( Environment*        ev,
  1278.                                 ODDraftKey            key,
  1279.                                   ODInfoType            partInfo,
  1280.                                 ODStorageUnitView*    storageUnitView,
  1281.                                 ODFrame*            scopeFrame )
  1282. {
  1283.     SOM_Trace("ListPart","ClonePartInfo");
  1284.     
  1285.     // Tell our frame info class to write itself out into the pre-
  1286.     // focused storage unit.
  1287.     ((CFrameInfo*) partInfo)->CloneInto(ev, key, storageUnitView, scopeFrame);
  1288. }
  1289.  
  1290. //------------------------------------------------------------------------------
  1291. // Method:        DisplayFrameAdded
  1292. // Origin:        ODPart
  1293. //
  1294. // Description:    This method is called in response to a frame being created for
  1295. //                the part.
  1296. //
  1297. //                The part records the existence of a new display frame in its
  1298. //                internal display frame list, as well as, verifies that the frame
  1299. //                is "set up" correctly (ie. valid viewType). The part also
  1300. //                creates and stores its "frame info" class in the new frame. 
  1301. //------------------------------------------------------------------------------
  1302.  
  1303. void ListPart::DisplayFrameAdded( Environment*    ev,
  1304.                                        ODFrame*        frame )
  1305. {
  1306.     WeBeHere("\pListPart::DisplayFrameAdded");
  1307.     SOM_Trace("ListPart","DisplayFrameAdded");
  1308.  
  1309.     // If we are being embedded in another part, the presentation field
  1310.     // will (most likely) be unset; we need to set it something meaningful.
  1311.     // The view field may also be unset, if so, we prefer to be displayed
  1312.     // in a frame view.
  1313.  
  1314.     if ( frame->GetPresentation(ev) != gGlobals->fMainPresentation )
  1315.         frame->SetPresentation(ev, gGlobals->fMainPresentation);
  1316.     
  1317.     if ( frame->GetViewType(ev) == kODNullTypeToken )
  1318.         frame->SetViewType(ev, gGlobals->fFrameView);
  1319.         
  1320.     // Hang our "state" info off of the new display frame. We use
  1321.     // the CFrameInfo object for activation, updating, and window
  1322.     // maintenance.
  1323.     CFrameInfo* frameInfo = new CFrameInfo(ODGetSession(ev,fSelf));
  1324.     frame->SetPartInfo(ev, (ODInfoType)frameInfo);
  1325.     
  1326.     // If the frame being added is a root frame, we know that a window
  1327.     // is associated with this frame. Notify ourselves that we need to 
  1328.     // clean it up when the frame goes away.
  1329.     if ( frame->IsRoot(ev) )
  1330.         frameInfo->SetShouldDisposeWindow(kODTrue);
  1331.     
  1332.     // The proxy class will refcount the frame passed to it, so we
  1333.     // don't need to worry about refcounting the display frame.
  1334.     CFrameProxy* proxy = new CFrameProxy;
  1335.     proxy->InitFrameProxy(ev,frame);
  1336.  
  1337.     // Add the proxy to the display frame collection.
  1338.     fDisplayFrames->Add(proxy);
  1339.  
  1340.     // Since we maintain a persistent list of weak references to our
  1341.     // display frames, having one added to the part dirties it.
  1342.     this->SetDirty(ev);
  1343. }
  1344.  
  1345. //------------------------------------------------------------------------------
  1346. // Method:        DisplayFrameConnected
  1347. // Origin:        ODPart
  1348. //
  1349. // Description:    This method is called when one of our display frames, previously
  1350. //                written out, is internalized. This method is called instead of
  1351. //                DisplayFrameAdded because a "new" frame is not being created;
  1352. //                an existing one is being reconstituted.
  1353. //
  1354. //                The part first checks to see if we can match its frame to an
  1355. //                ID in the Display frame list; if so, we put the frame into the
  1356. //                proxy. For frames we do not recognize, just add them.
  1357. //
  1358. // Warning:        This method may be calle,d during editor swapping, with a frame
  1359. //                not recognized by the part. This is ok. Just treat the case as
  1360. //                if a "new" frame were being added to the part.
  1361. //------------------------------------------------------------------------------
  1362.  
  1363. void ListPart::DisplayFrameConnected( Environment*    ev,
  1364.                                         ODFrame*        frame )
  1365. {
  1366.     WeBeHere("\pListPart::DisplayFrameConnected");
  1367.     SOM_Trace("ListPart","DisplayFrameConnected");
  1368.  
  1369.     // Iterate over our display collection to match the frame with
  1370.     // an existing proxy with the correct frame ID. If we find it,
  1371.     // replace the ID with the actual frame. If we don't find it,
  1372.     // treat it as a newly "added" frame.
  1373.     ODBoolean found = kODFalse;
  1374.     CListIterator fiter(fDisplayFrames);
  1375.     for ( CFrameProxy* proxy = (CFrameProxy*) fiter.First();
  1376.             fiter.IsNotComplete(); proxy = (CFrameProxy*) fiter.Next() )
  1377.     {
  1378.         if ( proxy->GetID() == frame->GetID(ev) )
  1379.         {
  1380.             // The proxy class will refcount the frame passed to it, so we
  1381.             // don't need to worry about refcounting the display frame.
  1382.             proxy->SetFrame(ev,frame);
  1383.             found = kODTrue;
  1384.         }
  1385.     }
  1386.  
  1387.     // Parts typically operate under the assumption that they have previous
  1388.     // knowledge of a frame before it is connected to it. This knowledge
  1389.     // should come from having read in the frame reference when the part
  1390.     // was internalized. If the frame is an "unknown", the part was probably
  1391.     // bound to another editors storage unit because the editor is missing or
  1392.     // the user changed the editor in the Info dialog. 
  1393.     if ( found )
  1394.     {
  1395.         // If a display frame is connected to us with an unrecognizable
  1396.         // presentation, we need to set it to something meaningful.
  1397.     
  1398.         if ( frame->GetPresentation(ev) != gGlobals->fMainPresentation )
  1399.             frame->SetPresentation(ev, gGlobals->fMainPresentation);
  1400.         
  1401.         if ( frame->IsRoot(ev) )
  1402.         {
  1403.             // If the frame being added is a root frame, we know that a window
  1404.             // is associated with this frame. Notify ourselves that we need to 
  1405.             // clean it up when the frame goes away.
  1406.             CFrameInfo* frameInfo = (CFrameInfo*) frame->GetPartInfo(ev);
  1407.             frameInfo->SetShouldDisposeWindow(kODTrue);
  1408.             
  1409.             // In addition, we need to verify that the frame is in "frame" view.
  1410.             // If the user dragged an icon from a document to Finder and then
  1411.             // opens the resultant document, the view would be "icon". However
  1412.             // displaying a icon is useless, so we need to change the view to
  1413.             // frame.
  1414.             if ( frame->GetViewType(ev) != gGlobals->fFrameView )
  1415.                 frame->SetViewType(ev, gGlobals->fFrameView);    
  1416.         }
  1417.     }
  1418.     else
  1419.     {
  1420.         // If an unrecognizable frame is connected to us, treat it like a "new"
  1421.         // frame and call our method to add it.
  1422.         this->DisplayFrameAdded(ev, frame);
  1423.     }
  1424. }
  1425.  
  1426. //------------------------------------------------------------------------------
  1427. // Method:        DisplayFrameRemoved
  1428. // Origin:        ODPart
  1429. //
  1430. // Description:    This method is called in response to a frame being removed from
  1431. //                the part.
  1432. //
  1433. //                The part removes the frame from its internal display frame list
  1434. //                and reliquishes any foci that it still owned. Lastly, if the
  1435. //                frame has a source frame (it was the root frame of a part
  1436. //                window), we will record the part window bounds so that any
  1437. //                subsequent part windows opened on the source frame will appear
  1438. //                in the same location.
  1439. //------------------------------------------------------------------------------
  1440.  
  1441. void ListPart::DisplayFrameRemoved( Environment*    ev,
  1442.                                       ODFrame*        frame )
  1443. {
  1444.     WeBeHere("\pListPart::DisplayFrameRemoved");
  1445.     SOM_Trace("ListPart","DisplayFrameRemoved");
  1446.  
  1447.     TRY
  1448.         CFrameInfo* frameInfo = (CFrameInfo*) frame->GetPartInfo(ev);
  1449.     
  1450.         // Make sure the frame going away does not own any foci. Forgetting
  1451.         // to do this, will cause a "refcounting" error when the frame
  1452.         // is deleted by the draft.
  1453.         this->RelinquishAllFoci(ev, frame);
  1454.  
  1455.         // Clean up the display frame.
  1456.         this->CleanupDisplayFrame(ev, frame, kFrameRemoved);
  1457.         // Clean up any associated window.
  1458.         this->CleanupWindow(ev, frame);
  1459.         // Dispose of the frame's runtime state info.
  1460.         frame->SetPartInfo(ev, (ODInfoType) kODNULL);
  1461.         ODDeleteObject(frameInfo);
  1462.         
  1463.         // Remove the display frame from our collection.
  1464.         CListIterator fiter(fDisplayFrames);
  1465.         for ( CFrameProxy* proxy = (CFrameProxy*) fiter.First();
  1466.                 fiter.IsNotComplete(); proxy = (CFrameProxy*) fiter.Next() )
  1467.         {
  1468.             if ( ODObjectsAreEqual(ev, proxy->GetFrame(ev), frame) )
  1469.             {
  1470.                 // Delete the proxy object and its contents. The frame's
  1471.                 // refcount will be decremented in the proxy destructor.
  1472.                 fiter.RemoveCurrent();
  1473.                 delete proxy;
  1474.             }
  1475.         }
  1476.  
  1477.         // Since we maintain a persistent list of weak references to our
  1478.         // display frames, having one removed from the part dirties it.
  1479.         this->SetDirty(ev);
  1480.     
  1481.     CATCH_ALL
  1482.         // Alert the user of the problem.
  1483.         this->DoDialogBox(ev, frame, kErrorBoxID, kErrRemoveFrame);
  1484.         // Change the exception value, so the DocShell doesn't display an
  1485.         // error dialog.
  1486.         SetErrorCode(kODErrAlreadyNotified);
  1487.         // Alert the caller.
  1488.         RERAISE;
  1489.     ENDTRY
  1490. }
  1491.  
  1492. //------------------------------------------------------------------------------
  1493. // Method:        DisplayFrameClosed
  1494. // Origin:        ODPart
  1495. //
  1496. // Description:    This method is called in response to a frame being closed as a
  1497. //                result of the document having been closed by the user.
  1498. //
  1499. //                The part behaves much the same way that it would if a frame were
  1500. //                removed (see above), except that we don't need to cache runtime
  1501. //                information. 
  1502. //------------------------------------------------------------------------------
  1503.  
  1504. void ListPart::DisplayFrameClosed( Environment*    ev,
  1505.                                      ODFrame*        frame )
  1506. {
  1507.     WeBeHere("\pListPart::DisplayFrameClosed");
  1508.     SOM_Trace("ListPart","DisplayFrameClosed");
  1509.  
  1510.     TRY
  1511.         CFrameInfo* frameInfo = (CFrameInfo*) frame->GetPartInfo(ev);
  1512.     
  1513.         // Make sure the frame going away does not own any foci. Forgetting
  1514.         // to do this, will cause a "refcounting" error when the frame
  1515.         // is deleted by the draft.
  1516.         this->RelinquishAllFoci(ev, frame);
  1517.  
  1518.         // Clean up the display frame.
  1519.         this->CleanupDisplayFrame(ev, frame, kFrameClosed);
  1520.         // Clean up any associated window.
  1521.         this->CleanupWindow(ev, frame);
  1522.         // Dispose of the frame's runtime state info.
  1523.         frame->SetPartInfo(ev, (ODInfoType) kODNULL);
  1524.         ODDeleteObject(frameInfo);
  1525.         
  1526.         // Remove the display frame from our collection.
  1527.         CListIterator fiter(fDisplayFrames);
  1528.         for ( CFrameProxy* proxy = (CFrameProxy*) fiter.First();
  1529.                 fiter.IsNotComplete(); proxy = (CFrameProxy*) fiter.Next() )
  1530.         {
  1531.             if ( proxy->GetID() == frame->GetID(ev) )
  1532.             {
  1533.                 // Release the frame reference, but don't get rid of the
  1534.                 // proxy object because "closed" frames may be reconnected
  1535.                 // before the document is really closed.
  1536.                 proxy->Purge(ev);
  1537.             }
  1538.         }
  1539.         
  1540.     CATCH_ALL
  1541.         // Alert the user of the problem.
  1542.         this->DoDialogBox(ev, frame, kErrorBoxID, kErrRemoveFrame);
  1543.         // Change the exception value, so the DocShell doesn't display an
  1544.         // error dialog.
  1545.         SetErrorCode(kODErrAlreadyNotified);
  1546.         // Alert the caller.
  1547.         RERAISE;
  1548.     ENDTRY
  1549. }
  1550.  
  1551. //------------------------------------------------------------------------------
  1552. // Method:        CleanupDisplayFrame
  1553. // Origin:        ListPart
  1554. //
  1555. // Description:    This method is called when a frame has been closed or removed.
  1556. //                The method cleans up the references and state information stored
  1557. //                in the CFrameInfo class.
  1558. //------------------------------------------------------------------------------
  1559.  
  1560. void ListPart::CleanupDisplayFrame(    Environment*    ev,
  1561.                                         ODFrame*        frame,
  1562.                                         ODBoolean        frameRemoved )
  1563. {
  1564.     WeBeHere("\pListPart::CleanupDisplayFrame");
  1565.     SOM_Trace("ListPart","CleanupDisplayFrame");
  1566.  
  1567.     ODError        error = noErr;
  1568.     CFrameInfo*    frameInfo = (CFrameInfo*) frame->GetPartInfo(ev);
  1569.  
  1570.     TRY
  1571.         // If we are the root of a child window, we need to notify
  1572.         // our source frame that we are going away.
  1573.         if ( frameInfo->HasSourceFrame() )
  1574.         {
  1575.             ODFrame* sourceFrame = frameInfo->GetSourceFrame(ev);
  1576.             CFrameInfo* sourceFrameInfo = (CFrameInfo*) sourceFrame->GetPartInfo(ev);
  1577.  
  1578.             if ( frameRemoved )
  1579.             {
  1580.                 // Invalidate the source frame. We do this because the
  1581.                 // source frame may have a unique display when it has
  1582.                 // been opened into a part window. This forces the
  1583.                 // frame to redraw "not opened".
  1584.                 sourceFrame->Invalidate(ev, kODNULL, kODNULL);
  1585.             }
  1586.             
  1587.             // Tell the source frame that its dependent is going away.
  1588.             sourceFrameInfo->ReleaseDependentFrame(ev);            
  1589.  
  1590.             // Release our reference to the source frame.
  1591.             frameInfo->ReleaseSourceFrame(ev);
  1592.  
  1593.             // If the frame is the root, it is a part window going away
  1594.             // and we need to notify our source frame that it no longer
  1595.             // has a part window.
  1596.             if ( frame->IsRoot(ev) )
  1597.                 sourceFrameInfo->SetPartWindow(ev, kODNULL);
  1598.         }
  1599.     CATCH_ALL
  1600.         error = ErrorCode();
  1601.     ENDTRY
  1602.     
  1603.     TRY
  1604.         // If the frame was removed from the document, we need to remove
  1605.         // any child window displaying that frame.
  1606.         if ( frameRemoved )
  1607.         {
  1608.             // If we have a child window, we need to close it.
  1609.             ODWindow* window = frameInfo->AcquirePartWindow(ev);
  1610.  
  1611.             if ( window )
  1612.             {
  1613.                 frameInfo->SetPartWindow(ev, kODNULL);
  1614.                 window->CloseAndRemove(ev);
  1615.             }
  1616.         }
  1617.     CATCH_ALL
  1618.         error = ErrorCode();
  1619.     ENDTRY
  1620.  
  1621.     TRY
  1622.         // If we have dependent frames, we need to notify them that we
  1623.         // are going away.
  1624.     
  1625.         if ( frameInfo->HasDependentFrame() )
  1626.         {
  1627.             // Get the frame that is dependent on this one. We can safely
  1628.             // do this because we only reference our own display frames.
  1629.             ODFrame* dependentFrame = frameInfo->GetDependentFrame(ev);
  1630.             CFrameInfo* dependentFrameInfo = (CFrameInfo*) dependentFrame->GetPartInfo(ev);
  1631.  
  1632.             // Tell the dependent frame that its source is going away.
  1633.             dependentFrameInfo->ReleaseSourceFrame(ev);
  1634.             
  1635.             // Release our reference to the dependent frame.
  1636.             frameInfo->ReleaseDependentFrame(ev);
  1637.         }
  1638.     CATCH_ALL
  1639.         error = ErrorCode();
  1640.     ENDTRY
  1641.     
  1642.     // If anything went wrong, signal an error.
  1643.     THROW_IF_ERROR(error);
  1644. }
  1645.  
  1646. //------------------------------------------------------------------------------
  1647. // Method:        AttachSourceFrame
  1648. // Origin:        ODPart
  1649. //
  1650. // Description:    If the part which we are contained in is opened into a part
  1651. //                window, it is required to iterate over its embedded frames and
  1652. //                add new display frames in the part window. After each new
  1653. //                embedded frame is created, this method will be called.
  1654. //
  1655. //                Given all that, and given our lack of interesting
  1656. //                content, we just validate the frame and attach it to its source.
  1657. //------------------------------------------------------------------------------
  1658.  
  1659. void ListPart::AttachSourceFrame( Environment*    ev,
  1660.                                     ODFrame*        frame,
  1661.                                     ODFrame*        sourceFrame )
  1662. {
  1663.     WeBeHere("\pListPart::AttachSourceFrame");
  1664.     SOM_Trace("ListPart","AttachSourceFrame");
  1665.  
  1666.     // Tell the new frame about its source.
  1667.     CFrameInfo* frameInfo = (CFrameInfo*) frame->GetPartInfo(ev);
  1668.     frameInfo->SetSourceFrame(ev, sourceFrame);
  1669.     
  1670.     // And tell the source about its new dependent.
  1671.     frameInfo = (CFrameInfo*) sourceFrame->GetPartInfo(ev);
  1672.     frameInfo->SetDependentFrame(ev, frame);
  1673.     
  1674.     // In both cases, refcounting of the frame and sourceFrame is
  1675.     // handled by the CFrameInfo class.
  1676. }
  1677.  
  1678. //------------------------------------------------------------------------------
  1679. // Method:        ViewTypeChanged
  1680. // Origin:        ODPart
  1681. //
  1682. // Description:    This method is called in response to one of our display frame's
  1683. //                viewType field being modified. We call this method on ourselves
  1684. //                when new display frames are added, but it call also be called
  1685. //                when the user changes the view in the "part info" dialog.
  1686. //
  1687. //                The part first loads the appropriate view icons if needed and
  1688. //                then calculates a new "used" shape based on the bounds of the
  1689. //                new view type. If any problems occur while changing the view,
  1690. //                the part defaults back to frame view (the part's default view).
  1691. //------------------------------------------------------------------------------
  1692.  
  1693. void ListPart::ViewTypeChanged( Environment*    ev,
  1694.                                   ODFrame*        frame )
  1695. {
  1696.     WeBeHere("\pListPart::ViewTypeChanged");
  1697.     SOM_Trace("ListPart","ViewTypeChanged");
  1698.  
  1699.     ODTypeToken    view = frame->GetViewType(ev);
  1700.     
  1701.     // If the new view is Thumbnail, load the picture resource.
  1702.     if ( view == gGlobals->fThumbnailView )
  1703.         this->GenerateThumbnail(ev, frame);
  1704.             
  1705.     // Change this frame's used shape to match the new view setting.
  1706.     TempODShape newUsedShape = this->CalcNewUsedShape(ev, frame);    
  1707.  
  1708.     this->AdjustFacets(ev, frame);
  1709.  
  1710.     frame->Invalidate(ev, kODNULL, kODNULL);
  1711.     frame->ChangeUsedShape(ev, newUsedShape, kODNULL);
  1712.     frame->Invalidate(ev, kODNULL, kODNULL);
  1713. }
  1714.  
  1715. //------------------------------------------------------------------------------
  1716. // Method:        CalcNewUsedShape
  1717. // Origin:        ListPart
  1718. //
  1719. // Description:    This method is called in response to one of display frame's view
  1720. //                being changed. The method calculates the appropriate usedShape
  1721. //                for the new view type.
  1722. //------------------------------------------------------------------------------
  1723.  
  1724. ODShape* ListPart::CalcNewUsedShape( Environment*    ev,
  1725.                                          ODFrame*        frame )
  1726. {
  1727.     WeBeHere("\pListPart::CalcNewUsedShape");
  1728.     SOM_Trace("ListPart","CalcNewUsedShape");
  1729.  
  1730.     ODShape* usedShape = kODNULL;        ODVolatile(usedShape);
  1731.     RgnHandle usedRgn;                    ODVolatile(usedRgn);
  1732.     
  1733.     // If the view is "frame", we intentionally return a nil shape;
  1734.     // doing so, will reset the used shape to equal the frame shape.
  1735.  
  1736.     ODTypeToken view = frame->GetViewType(ev);
  1737.  
  1738.     if ( view == gGlobals->fLargeIconView ||
  1739.             view == gGlobals->fSmallIconView ||
  1740.             view == gGlobals->fThumbnailView )
  1741.     {
  1742.         TRY
  1743.             Rect bounds;
  1744.             usedRgn = ODNewRgn();
  1745.  
  1746.             if ( view == gGlobals->fLargeIconView || view == gGlobals->fSmallIconView )
  1747.             {
  1748.                 CUsingLibraryResources res;
  1749.  
  1750.                 // Set the bounds rect for the icon size.
  1751.                 SetRect(&bounds, 0, 0,
  1752.                         (view == gGlobals->fLargeIconView) ? kODLargeIconSize : kODSmallIconSize,
  1753.                         (view == gGlobals->fLargeIconView) ? kODLargeIconSize : kODSmallIconSize);
  1754.  
  1755.                 // Convert the icon mask into a Region.
  1756.                 THROW_IF_ERROR( IconIDToRgn(usedRgn, &bounds, atAbsoluteCenter, kBaseResourceID) );
  1757.             }
  1758.             else if ( view == gGlobals->fThumbnailView )
  1759.             {    
  1760.                 bounds = (**(PicHandle)fThumbnail).picFrame;
  1761.                 RectRgn(usedRgn,&bounds);
  1762.             }
  1763.         
  1764.             usedShape = frame->CreateShape(ev);
  1765.             usedShape->SetQDRegion(ev, usedRgn);
  1766.                             
  1767.         CATCH_ALL
  1768.             ODSafeReleaseObject(usedShape);
  1769.             ODDisposeHandle((ODHandle)usedRgn);
  1770.             usedShape = kODNULL;
  1771.         ENDTRY
  1772.     }
  1773.         
  1774.     return usedShape;
  1775. }
  1776.  
  1777. //------------------------------------------------------------------------------
  1778. // Method:        UpdateFrame
  1779. // Origin:        ListPart
  1780. //
  1781. // Description:    This method is called in response to one of our
  1782. //------------------------------------------------------------------------------
  1783.  
  1784. void ListPart::UpdateFrame( Environment*    ev,
  1785.                              ODFrame*        frame,
  1786.                              ODTypeToken    view,
  1787.                              ODShape*        usedShape )
  1788. {
  1789.     WeBeHere("\pListPart::UpdateFrame");
  1790.     SOM_Trace("ListPart","UpdateFrame");
  1791.  
  1792.     TRY
  1793.         // Update the frame to have the new view and UsedShape.
  1794.         frame->Invalidate(ev, kODNULL, kODNULL);
  1795.         frame->SetViewType(ev, view);
  1796.         frame->ChangeUsedShape(ev, usedShape, kODNULL);
  1797.         frame->Invalidate(ev, kODNULL, kODNULL);
  1798.     CATCH_ALL
  1799.         // Failing isn't great, but we can live with it, so don't set ev.
  1800.     ENDTRY
  1801. }
  1802.  
  1803. //------------------------------------------------------------------------------
  1804. // Method:        GenerateThumbnail
  1805. // Origin:        ListPart
  1806. //
  1807. // Description:    This method is called by the part to generate a thumbnail view
  1808. //                from the current content.
  1809. //
  1810. //                The part has no content, so we merely load a picture.
  1811. //------------------------------------------------------------------------------
  1812.  
  1813. void ListPart::GenerateThumbnail( Environment*    ev,
  1814.                                     ODFrame*        frame )
  1815. {
  1816.     WeBeHere("\pListPart::GenerateThumbnail");
  1817.     SOM_Trace("ListPart","GenerateThumbnail");
  1818.     
  1819.     // In cases where a part has been instantiated from scratch and has no
  1820.     // content (yet), it is appropriate to display a PICT or some graphic
  1821.     // in place of a "real" thumbnail.
  1822.     
  1823.     if ( fThumbnail == kODNULL )
  1824.         LoadThumbnail(ev, fsomSelf, &fThumbnail);
  1825.  
  1826.     // If we were unable to load the PICT resource for whatever reason
  1827.     // we will default back to a "frame" view and throw the Resource
  1828.     // Manager error as an exception.
  1829.     if ( fThumbnail == kODNULL )
  1830.     {
  1831.         frame->ChangeViewType(ev, gGlobals->fFrameView);
  1832.         // There is a bug in ResError, when resources are not found,
  1833.         // which may cause noErr to be returned. If that is the case,
  1834.         // we throw resNotFound.
  1835.         THROW_IF_ERROR((ODError)ResError());
  1836.         THROW(resNotFound);
  1837.     }
  1838. }
  1839.  
  1840. //------------------------------------------------------------------------------
  1841. // Method:        FrameShapeChanged
  1842. // Origin:        ODPart
  1843. //
  1844. // Description:    This method is called in response to a frame's shape being
  1845. //                altered, either by the user or the part we are embedded in.
  1846. //
  1847. //                To keep all dependent frames in sync, we need to propogate the
  1848. //                new frame shape the frames dependent on the changed frame. This
  1849. //                is done by observing the display frames stored in the frame info
  1850. //                and calling RequestFrameShape for each.
  1851. //------------------------------------------------------------------------------
  1852.  
  1853. void ListPart::FrameShapeChanged( Environment*    ev,
  1854.                                     ODFrame*        frame )
  1855. {
  1856.     WeBeHere("\pListPart::FrameShapeChanged");
  1857.     SOM_Trace("ListPart","FrameShapeChanged");
  1858.  
  1859. // ES 11/16/95
  1860.     if (frame->IsRoot(ev))
  1861.         {
  1862.         Rect r1, r2;
  1863.         ODWindow*     odwnd = frame->AcquireWindow(ev);
  1864.         WindowPtr    wnd   = (WindowPtr)odwnd->GetPlatformWindow(ev);
  1865.         odwnd->Release(ev);
  1866.         r1 = wnd->portRect;
  1867.         r2 = r1;
  1868.         MyAdjustRectFacet(ev, &r1);
  1869.         if (!EqualRect(&r1, &r2))
  1870.             {
  1871.             ::SizeWindow(wnd, r1.right, r1.bottom, true);
  1872.             ODWindow*     odwnd = frame->AcquireWindow(ev);
  1873.             odwnd->AdjustWindowShape(ev);
  1874.             odwnd->Release(ev);
  1875.             return;
  1876.             }
  1877.         }
  1878.  
  1879.     TempODShape    frameShape = frame->AcquireFrameShape(ev, kODNULL);
  1880.     CFrameInfo*    frameInfo = (CFrameInfo*) frame->GetPartInfo(ev);
  1881.     ODFrame*    displayFrame;
  1882.  
  1883. // ES 11/13/95
  1884.     ODRect odrct;
  1885.     Rect rct;
  1886.     frameShape->GetBoundingBox(ev, &odrct);
  1887.     odrct.AsQDRect(rct);
  1888.     MyAdjustRectFacet(ev, &rct);
  1889.     odrct = (rct);
  1890.     frameShape->SetRectangle(ev, &odrct);
  1891.     
  1892.     this->AdjustFacets(ev, frame);
  1893.  
  1894.     // If the frame is the root frame of a part or document window, it should
  1895.     // have no effect on its dependent frames or source frame.
  1896.  
  1897.     if ( !frame->IsRoot(ev) )
  1898.     {
  1899.         
  1900.         if ( frameInfo->HasSourceFrame() )
  1901.         {
  1902.             displayFrame = frameInfo->GetSourceFrame(ev);
  1903.             
  1904.             TempODShape frameShapeCopy = frameShape->Copy(ev);
  1905.             TempODShape returnShape = displayFrame->RequestFrameShape(ev, frameShapeCopy, kODNULL);
  1906.             
  1907. // ES 11/14/95
  1908.             this->AdjustFacets(ev, displayFrame);
  1909.             displayFrame->Invalidate(ev, kODNULL, kODNULL);
  1910.         }
  1911.     
  1912.         if ( frameInfo->HasDependentFrame() )
  1913.         {
  1914.             displayFrame = frameInfo->GetDependentFrame(ev);
  1915.             
  1916.             TempODShape frameShapeCopy = frameShape->Copy(ev);
  1917.             TempODShape returnShape = displayFrame->RequestFrameShape(ev, frameShapeCopy, kODNULL);
  1918.                 
  1919. // ES 11/14/95
  1920.             this->AdjustFacets(ev, displayFrame);
  1921.             displayFrame->Invalidate(ev, kODNULL, kODNULL);
  1922.         }
  1923.     }
  1924. }
  1925.  
  1926. //------------------------------------------------------------------------------
  1927. // Method:        Open
  1928. // Origin:        ODPart
  1929. //
  1930. // Description:    This method is called when OpenDoc, a containing part, or the
  1931. //                active editor would like to open a frame into a seperate window.
  1932. //                If a source frame is passed into this method, the editor is
  1933. //                being asked one of two things. If the frame is the root, we are
  1934. //                being asked to open an existing document. If the frame is not
  1935. //                the root, we are being asked to open a part window. If a source
  1936. //                frame is not specified, the editor is being asked to open a new
  1937. //                window.
  1938. //------------------------------------------------------------------------------
  1939.  
  1940. ODID ListPart::Open( Environment*    ev, ODFrame* frame )
  1941. {
  1942.     WeBeHere("\pListPart::Open");
  1943.     SOM_Trace("ListPart","Open");
  1944.  
  1945.     ODID windowID;
  1946.     TempODWindow window(kODNULL);
  1947.  
  1948.     WindowProperties* windowProperties = kODNULL;
  1949.     ODVolatile(windowProperties);
  1950.  
  1951.     TRY
  1952.         // Because the frame parameter being passed to us can be one of
  1953.         // three things, we must determine what it is; either the root
  1954.         // frame of a existing document, the source frame for a part
  1955.         // window, or null if we are opening a new document.
  1956.     
  1957.         if ( frame == kODNULL )
  1958.         {
  1959.             // Calculate the bounding rectangle for a new window
  1960.             Rect windowRect = this->CalcPartWindowSize(ev, kODNULL);
  1961.             // Get the default setting for a document window.
  1962.             windowProperties = this->GetDefaultWindowProperties(ev, kODNULL, &windowRect);
  1963.             // Create a Mac Window and register it with OpenDoc.
  1964.             window = this->CreateWindow(ev, kODNULL, kODFrameObject, windowProperties);
  1965.         }
  1966.         else if ( frame->IsRoot(ev) )
  1967.         {
  1968.             // Get the previously saved settings for the document window.
  1969.             windowProperties = this->GetSavedWindowProperties(ev, frame);
  1970.             
  1971.             if ( windowProperties == kODNULL )
  1972.             {
  1973.                 // Calculate the bounding rectangle for a new window
  1974.                 Rect windowRect = this->CalcPartWindowSize(ev, frame);
  1975.                 // Get the default setting for a document window.
  1976.                 windowProperties = this->GetDefaultWindowProperties(ev, kODNULL, &windowRect);
  1977.             }
  1978.  
  1979.             // Create a Mac Window and register it with OpenDoc.
  1980.             window = this->CreateWindow(ev, frame, kODFrameObject, windowProperties);
  1981.             
  1982.             // We release the source frame here because we didn't call
  1983.             // EndGetWindowProperties and becuase we are done with it.
  1984.             ODReleaseObject(ev, windowProperties->sourceFrame);
  1985.         }
  1986.         else // frame is a source frame
  1987.         {
  1988.             window = this->AcquireFramesWindow(ev, frame);
  1989.     
  1990.             if ( window == kODNULL )
  1991.             {
  1992.                 // Calculate the bounding rectangle for a new window
  1993.                 Rect windowRect = this->CalcPartWindowSize(ev, frame);
  1994.                 // Get the default setting for a document window.
  1995.                 windowProperties = this->GetDefaultWindowProperties(ev, frame, &windowRect);
  1996.                 // Create a Mac Window and register it with OpenDoc.
  1997.                 window = this->CreateWindow(ev, kODNULL, kODFrameObject, windowProperties);
  1998.                 
  1999.                 // Tell the source frame that it is opened in a part window.
  2000.                 CFrameInfo* frameInfo = (CFrameInfo*) frame->GetPartInfo(ev);
  2001.                 frameInfo->SetPartWindow(ev, window);
  2002.             }
  2003.         }
  2004.     
  2005.         // Create the window's root facet.
  2006.         window->Open(ev);
  2007.         // Make the window visible.
  2008.         window->Show(ev);
  2009.         // Activate and select the window.
  2010.         window->Select(ev);
  2011.     
  2012.         // Cleanup allocate memory.
  2013.         ODDeleteObject(windowProperties);
  2014.         
  2015.         // Get window id to return.
  2016.         windowID = (window ? window->GetID(ev) : kODNULLID);
  2017.     
  2018.     CATCH_ALL
  2019.         // If we threw early, the source frame's refcount may be too high.
  2020.         if ( windowProperties )
  2021.             ODSafeReleaseObject(windowProperties->sourceFrame);
  2022.         // Cleanup the created items.
  2023.         ODDeleteObject(windowProperties);
  2024.         windowID = kODNULLID;
  2025.         // Alert the caller.
  2026.         RERAISE;
  2027.     ENDTRY
  2028.  
  2029.     return windowID;
  2030. }
  2031.  
  2032. //------------------------------------------------------------------------------
  2033. // Method:        AcquireFramesWindow
  2034. // Origin:        ListPart
  2035. //
  2036. // Description:    This method is called by the part when a frame, that has been
  2037. //                previously opened, is being opened again.
  2038. //
  2039. //                The method retrieves the existing window for the frame and
  2040. //                returns it.                
  2041. //------------------------------------------------------------------------------
  2042.  
  2043. ODWindow* ListPart::AcquireFramesWindow(    Environment*    ev,
  2044.                                                ODFrame*        frame )
  2045. {
  2046.     WeBeHere("\pListPart::AquireFramesWindow");
  2047.     SOM_Trace("ListPart","AquireFramesWindow");
  2048.  
  2049.     CFrameInfo* frameInfo = (CFrameInfo*) frame->GetPartInfo(ev);
  2050.     ODWindow* window = frameInfo->AcquirePartWindow(ev);
  2051.  
  2052.     return window;
  2053. }
  2054.     
  2055. //------------------------------------------------------------------------------
  2056. // Method:        CreateWindow
  2057. // Origin:        ListPart
  2058. //
  2059. // Description:    This method is called by the part when a window needs to be
  2060. //                created for a frame being opened.
  2061. //
  2062. //                The part uses the information passed in windowProperties to 
  2063. //                create the appropriate window. The generated window is
  2064. //                registered with OpenDoc as a new window (RegisterWindow) or as a
  2065. //                window from an existing document (RegisterWindowForFrame).
  2066. //------------------------------------------------------------------------------
  2067.  
  2068. ODWindow* ListPart::CreateWindow( Environment*         ev,
  2069.                                     ODFrame*            frame,
  2070.                                     ODType                frameType,
  2071.                                     WindowProperties*    windowProperties)
  2072. {
  2073.     WeBeHere("\pListPart::CreateWindow");
  2074.     SOM_Trace("ListPart","CreateWindow");
  2075.  
  2076.     ODPlatformWindow    platformWindow    = kODNULL;
  2077.     ODWindow*            window            = kODNULL;
  2078.  
  2079. // ES 11/13/95
  2080.     MyAdjustRectFacet(ev, &(windowProperties->boundsRect));
  2081.  
  2082.     // Using the name and the calculated rectangle, create a new window.
  2083.     // Note that we are allocating the window record in temp mem using
  2084.     // the OpenDoc memory mgr. This helps reduce app heap usage.
  2085.     // In addition, OpenDoc requires that all new windows be initially hidden
  2086.     // so that it can correctly layer windows/palettes.
  2087.     platformWindow = NewCWindow((Ptr)ODNewPtr(sizeof(WindowRecord)),
  2088.                                 &(windowProperties->boundsRect),
  2089.                                 windowProperties->title,
  2090.                                 kODFalse, /* visible */
  2091.                                 windowProperties->procID,
  2092.                                 (WindowPtr)-1L,
  2093.                                 windowProperties->hasCloseBox,
  2094.                                 windowProperties->refCon);
  2095.  
  2096.     if ( platformWindow )
  2097.     {
  2098.         TRY
  2099.             ODWindowState* windowState = ODGetSession(ev,fSelf)->GetWindowState(ev);
  2100.             
  2101.             // Shoud the window be saved in the document? Yes if the root frame is
  2102.             // persistent.
  2103.             ODBoolean saveWindow = (ODISOStrCompare(frameType,kODFrameObject) == 0);
  2104.             
  2105.             // Tell the window object that we will be disposing the window record
  2106.             // when the root frame is closed/removed.
  2107.             ODBoolean shouldDispose = kODFalse;
  2108.                                 
  2109.             // Determine whether we are creating a new window (frame is null),
  2110.             // or opening a previous saved window (frame is valid).
  2111.             
  2112.             if ( frame == kODNULL )
  2113.             {                                
  2114.                 // Tell OpenDoc about it by creating an OpenDoc window object.
  2115.                 window = windowState->
  2116.                             RegisterWindow(ev, 
  2117.                                 platformWindow,                    // Macintosh WindowPtr
  2118.                                 frameType,                        // Frame type (Persistent/Non-persistent)
  2119.                                 windowProperties->isRootWindow,    // Is this a document window?
  2120.                                 windowProperties->isResizable,    // Is this window resizeable?
  2121.                                 windowProperties->isFloating,    // Is this window floating?
  2122.                                 saveWindow,                        // Should this window be persistent?
  2123.                                 shouldDispose,                    // (see comment above)
  2124.                                 fSelf,                            // Part reference to us
  2125.                                 gGlobals->fFrameView,            // What view should the window have?
  2126.                                 gGlobals->fMainPresentation,    // What presentation should the window have?
  2127.                                 windowProperties->sourceFrame);    // The display frame being opened, if any
  2128.             }
  2129.             else
  2130.             {
  2131.                 // Tell OpenDoc about it by creating an OpenDoc window object.
  2132.                 window = windowState->
  2133.                             RegisterWindowForFrame(ev, 
  2134.                                 platformWindow,                    // Macintosh WindowPtr
  2135.                                 frame,                             // Frame type (Persistent/Non-persistent)
  2136.                                 windowProperties->isRootWindow,    // Is this a document window?
  2137.                                 windowProperties->isResizable,    // Is this window resizeable?
  2138.                                 windowProperties->isFloating,    // Is this window floating?
  2139.                                 saveWindow,                        // Should this window be persistent?
  2140.                                 shouldDispose,                    // (see comment above)
  2141.                                 windowProperties->sourceFrame);    // The display frame being opened, if any
  2142.             }
  2143.             
  2144.         CATCH_ALL
  2145.             // Cleanup Macintosh Window.
  2146.             CloseWindow(platformWindow);
  2147.             ODDisposePtr(platformWindow);
  2148.             // Get the right error message for the problem.
  2149.             ODSShort errMsgNum = (!frame && windowProperties->sourceFrame)
  2150.                                     ? kErrCantOpenPartWindow : kErrCantOpenDocWindow;
  2151.             // Alert the user of the problem.
  2152.             this->DoDialogBox(ev, frame, kErrorBoxID, errMsgNum);
  2153.             // Change the exception value, so the DocShell doesn't display an
  2154.             // error dialog.
  2155.             SetErrorCode(kODErrAlreadyNotified);
  2156.             // Alert the caller.
  2157.             RERAISE;
  2158.         ENDTRY
  2159.     }
  2160.  
  2161.     return window;
  2162. }
  2163.     
  2164. //------------------------------------------------------------------------------
  2165. // Method:        CleanupWindow
  2166. // Origin:        ListPart
  2167. //
  2168. // Description:    This method is called by the part when a window needs to be
  2169. //                cleaned up for a frame being closed/removed.
  2170. //
  2171. //                The part deallocates the window buffer allocated in the
  2172. //                CreateWindow() method.
  2173. //------------------------------------------------------------------------------
  2174.  
  2175. void ListPart::CleanupWindow( Environment*     ev,
  2176.                                 ODFrame*        frame )
  2177. {
  2178.     WeBeHere("\pListPart::CleanupWindow");
  2179.     SOM_Trace("ListPart","CleanupWindow");
  2180.     
  2181.        TRY
  2182.         CFrameInfo*    frameInfo = (CFrameInfo*) frame->GetPartInfo(ev);
  2183.         if ( frameInfo->ShouldDisposeWindow() )
  2184.         {
  2185.             TempODWindow window = frame->AcquireWindow(ev);
  2186.             THROW_IF_NULL(window);
  2187.             
  2188.             ODPlatformWindow windowPtr = window->GetPlatformWindow(ev);
  2189.             CloseWindow(windowPtr);
  2190.             ODDisposePtr(windowPtr);
  2191.         }
  2192.     CATCH_ALL
  2193.         this->DoDialogBox(ev, frame, kErrorBoxID, kErrWindowGone);
  2194.         // consume excpetion because it's not fatal.
  2195.     ENDTRY
  2196. }
  2197.  
  2198. //------------------------------------------------------------------------------
  2199. // Method:        GetDefaultWindowProperties
  2200. // Origin:        ListPart
  2201. //
  2202. // Description:    This method is called by the part when a new window is being
  2203. //                created. The method examines the frame which is being opened
  2204. //                a generates the default window parameters to pass to the
  2205. //                Mac Toolbox.
  2206. //------------------------------------------------------------------------------
  2207.  
  2208. WindowProperties*
  2209. ListPart::GetDefaultWindowProperties( Environment*     ev,
  2210.                                         ODFrame*        sourceFrame,
  2211.                                         Rect*            windowRect )
  2212. {
  2213.     SOM_Trace("ListPart","GetDefaultWindowProperties");
  2214.     
  2215.     WindowProperties* windowProperties = new WindowProperties;
  2216.  
  2217.     TRY
  2218.         // Calculate the offset for the window based on the sourceFrame.    
  2219.         if ( sourceFrame )
  2220.             this->CalcPartWindowPosition(ev, sourceFrame, windowRect);
  2221.         else
  2222.             OffsetRect(windowRect, kALittleNudge,
  2223.                         GetMBarHeight() + kMacWindowTitleBarHeight);    
  2224.     
  2225.         // Set the window bounds based on the calculated rect.
  2226.         windowProperties->boundsRect = *windowRect;
  2227.     
  2228.         // Get the part's name to use for the new window.
  2229.         TempODIText windowName = GetPartName(ev, fSelf, kListPartCategory);
  2230.         // Convert the ODIText into a Pascal string.
  2231.         GetITextString(windowName, windowProperties->title);
  2232.         
  2233.         // Fill in the other fields of the Window Properties struct.
  2234.         
  2235.         windowProperties->procID = zoomDocProc;
  2236.         windowProperties->hasCloseBox = kODTrue;
  2237.         windowProperties->refCon = (long) kODNULL;
  2238.         windowProperties->wasVisible = kODFalse;
  2239.         windowProperties->isResizable = kODTrue;
  2240.         windowProperties->isFloating = kODFalse;
  2241.         windowProperties->isRootWindow = sourceFrame ? kODFalse : kODTrue;
  2242.         windowProperties->shouldShowLinks = kODFalse;
  2243.         windowProperties->sourceFrame = sourceFrame;
  2244.     CATCH_ALL
  2245.         // Clean up and...
  2246.         ODDeleteObject(windowProperties);
  2247.         // Alert the caller.
  2248.         RERAISE;
  2249.     ENDTRY
  2250.     
  2251.     return windowProperties;
  2252. }
  2253.  
  2254. //------------------------------------------------------------------------------
  2255. // Method:        GetSavedWindowProperties
  2256. // Origin:        ListPart
  2257. //
  2258. // Description:    This method is called by the part to read in saved information
  2259. //                for a window from an existing document.
  2260. //------------------------------------------------------------------------------
  2261.  
  2262. WindowProperties* ListPart::GetSavedWindowProperties( Environment*     ev,
  2263.                                                           ODFrame*        frame )
  2264. {
  2265.     SOM_Trace("ListPart","GetSavedWindowProperties");
  2266.  
  2267.     WindowProperties* windowProperties = new WindowProperties;
  2268.     
  2269.     // If we fail to load the window properties from storage, delete
  2270.     // the structure so the calling code will behave appropriately.    
  2271.     if ( BeginGetWindowProperties(ev, frame, windowProperties) )
  2272.     {    
  2273.         // Note: We don't call EndGetWindowProperties because it releases the
  2274.         // source frame, which we will need after this method returns.
  2275.         
  2276.         // Get the part's name to use for the new window.
  2277.         TempODIText windowName = GetPartName(ev, fSelf, kListPartCategory);
  2278.         // Convert the ODIText into a Pascal string.
  2279.         GetITextString(windowName, windowProperties->title);
  2280.     
  2281.         // Verify the window is still visible on a monitor.
  2282.         
  2283.         RgnHandle windowRgn = ODNewRgn();
  2284.         ODBoolean repositionWindow = kODFalse;
  2285.         
  2286.         // We are only concerned with the window's title bar being
  2287.         // visible, so calcuate the titlebar rect from the current
  2288.         // window bounds.
  2289.         Rect adjustedBounds = windowProperties->boundsRect;
  2290.         adjustedBounds.bottom = adjustedBounds.top;
  2291.         adjustedBounds.top -= kMacWindowTitleBarHeight;
  2292.         
  2293.         // Intersect the monitor's region
  2294.         RectRgn(windowRgn, &adjustedBounds);
  2295.         SectRgn(windowRgn, GetGrayRgn(), windowRgn);
  2296.         
  2297.         if ( !EmptyRgn(windowRgn) )
  2298.         {
  2299.             // If the visible portion of the window is too small, we need
  2300.             // to reposition it.
  2301.             Rect intersectedBounds = (**windowRgn).rgnBBox;
  2302.             if ( (intersectedBounds.right-intersectedBounds.left < kMinHorzVisPortion) ||
  2303.                     (intersectedBounds.bottom-intersectedBounds.top < kMinVertVisPortion) )
  2304.                 repositionWindow = kODTrue;
  2305.         }
  2306.         else
  2307.         {
  2308.             // If the window is completely offscreen, we need to reposition it.
  2309.             repositionWindow = kODTrue;
  2310.         }
  2311.         ODDisposeHandle((ODHandle)windowRgn);
  2312.         
  2313.         // If not, we need to move it so the user can see it.
  2314.         if ( repositionWindow )
  2315.         {
  2316.             Rect windowRect = (windowProperties->boundsRect);
  2317.             // Move the window to {0,0} coordinates.
  2318.             OffsetRect(&windowRect, -windowRect.left, -windowRect.top);
  2319.             // Now move the window to the default window position.
  2320.             OffsetRect(&windowRect, kALittleNudge, GetMBarHeight() + kMacWindowTitleBarHeight);
  2321.             // Save the new window position in our windowProperties.
  2322.             windowProperties->boundsRect = windowRect;
  2323.         }
  2324.     }
  2325.     else
  2326.     {
  2327.         // If we were unable to re-load window properties, dispose of the
  2328.         // struct.
  2329.         ODDeleteObject(windowProperties);
  2330.     }
  2331.         
  2332.     return windowProperties;
  2333. }
  2334.  
  2335. //------------------------------------------------------------------------------
  2336. // Method:        CalcPartWindowSize
  2337. // Origin:        ListPart
  2338. //
  2339. // Description:    This method is called by the part to determine what size a new
  2340. //                window shoud be.
  2341. //------------------------------------------------------------------------------
  2342.  
  2343. Rect ListPart::CalcPartWindowSize( Environment*    ev,
  2344.                                       ODFrame*        sourceFrame )
  2345. {
  2346.     SOM_Trace("ListPart","CalcPartWindowSize");
  2347.  
  2348.     const ODSShort kOnePageWidth = 600;
  2349.     
  2350.     Rect    windowRect;
  2351.     ODRect    frameRect;
  2352.     
  2353.     // If a source frame is given, the part is being asked to open one of
  2354.     // its display frames into a part window. Otherwise, we are being opened
  2355.     // as the root frame of the current document and should size the window
  2356.     // accordingly.
  2357.  
  2358.     // Set up the child window's size to be that of the display frame being opened.
  2359.     if ( sourceFrame )
  2360.     {
  2361.         // Retrieve the fixed point bounding box for the frame.
  2362.         TempODShape frameShape = sourceFrame->AcquireFrameShape(ev, kODNULL);
  2363.         frameShape->GetBoundingBox(ev, &frameRect);
  2364.         
  2365.         // Convert that into a Quickdraw rectangle.
  2366.         FixedToIntRect(frameRect, windowRect);
  2367.     }
  2368.     // Otherwise, just open a large window.
  2369.     else
  2370.     {
  2371.         // (3 * kODLargeIconSize) prevents the window from covering the volume
  2372.         // icons on the desktop which is a violation of Macintosh HI Guidelines.
  2373.         
  2374.         SetRect(&windowRect, 0, 0,
  2375.                   ODQDGlobals.screenBits.bounds.right - (3 * kODLargeIconSize),
  2376.                   ODQDGlobals.screenBits.bounds.bottom
  2377.                       - GetMBarHeight() - kMacWindowTitleBarHeight - kALittleNudge);        
  2378.         
  2379.         if ( windowRect.right - windowRect.left > kOnePageWidth )
  2380.             windowRect.right = windowRect.left + kOnePageWidth;
  2381.     }
  2382.     
  2383.     return windowRect;
  2384. }
  2385.  
  2386. //------------------------------------------------------------------------------
  2387. // Method:        CalcPartWindowPosition
  2388. // Origin:        ListPart
  2389. //
  2390. // Description:    This method is called by the part to determine where to align
  2391. //                the new window (top left corner of the screen or tiled to a
  2392. //                frame).
  2393. //------------------------------------------------------------------------------
  2394.  
  2395. Rect ListPart::CalcPartWindowPosition( Environment*    ev,
  2396.                                           ODFrame*        frame,
  2397.                                           Rect*            partWindowBounds )
  2398. {
  2399.     SOM_Trace("ListPart","CalcPartWindowPosition");
  2400.  
  2401.     ODFacet*        activeFacet;
  2402.     ODShape*        frameShape;
  2403.     ODRect            bbox;
  2404.     Rect            bounds;
  2405.     
  2406.     // We need to know which facet of the frame we are opening to position
  2407.     // the child window.
  2408.     activeFacet = this->GetActiveFacetForFrame(ev, frame);
  2409.     
  2410.     // This should never occur, but if it did, it would be fatal.
  2411.     // So we will just pass back the same rectangle.
  2412.     if ( activeFacet == kODNULL )
  2413.         return *partWindowBounds;
  2414.     
  2415.     // For the purposes of tiling, we need the to know the area of the
  2416.     // document the frame occupies. We do this by getting the bouding
  2417.     // box and offsetting it by the aggregate external window transform
  2418.     // of the facet.
  2419.     
  2420.     frameShape = activeFacet->GetFrame(ev)->AcquireFrameShape(ev, kODNULL);
  2421.     TempODTransform windowFrameTransform = activeFacet->AcquireWindowFrameTransform(ev, kODNULL);
  2422.     TempODShape boundsShape = ODCopyAndRelease(ev, frameShape);
  2423.  
  2424.     // Translate the bounds rect into window coordinates.
  2425.     boundsShape->Transform(ev, windowFrameTransform);
  2426.     
  2427.     // Get and convert the bounding box into a QuickDraw rectangle.
  2428.     boundsShape->GetBoundingBox(ev, &bbox);
  2429.     FixedToIntRect(bbox, bounds);
  2430.         
  2431.     // We then call our method to tile the child window.
  2432.     *partWindowBounds = TilePartWindow(ev, &bounds, partWindowBounds);
  2433.     
  2434.     // Set the port and origin so we can convert the rect to
  2435.     // global Window Mgr coordinates.
  2436.     SetPort(activeFacet->GetCanvas(ev)->GetQDPort(ev));
  2437.     SetOrigin(0,-kMacWindowTitleBarHeight);
  2438.     
  2439.     // Convert the local coordinates to global Window Mgr coordinates.
  2440.     LocalToGlobal((Point*)(&(partWindowBounds->top)));
  2441.     LocalToGlobal((Point*)(&(partWindowBounds->bottom)));
  2442.     
  2443.     return *partWindowBounds;
  2444. }
  2445.  
  2446. //------------------------------------------------------------------------------
  2447. // Method:        GetActiveFacetForFrame
  2448. // Origin:        ListPart
  2449. //
  2450. // Description:    This method is called by the part when it needs to know what the
  2451. //                current active facet is.
  2452. //
  2453. //                The part uses this method specifically to find the facet of a
  2454. //                source frame when opening a part window.
  2455. //------------------------------------------------------------------------------
  2456.  
  2457. ODFacet* ListPart::GetActiveFacetForFrame( Environment*    ev,
  2458.                                              ODFrame*        frame )
  2459. {
  2460.     WeBeHere("\pListPart::GetActiveFacetForFrame");
  2461.     SOM_Trace("ListPart","GetActiveFacetForFrame");
  2462.  
  2463.     ODFacet*    facet = kODNULL;
  2464.     CFrameInfo*    frameInfo = (CFrameInfo*) frame->GetPartInfo(ev);
  2465.     
  2466.     // If the frame is active, and it should be, get the active facet
  2467.     // from the frame state info.
  2468.     if ( frameInfo->IsFrameActive() )
  2469.     {
  2470.         facet = frameInfo->GetActiveFacet();
  2471.     }
  2472.     else
  2473.     // Otherwise, iterate over the display frames looking for one
  2474.     // that has an active facet... there should be at least one.
  2475.     {
  2476.         TempODFrameFacetIterator fiter(ev, frame);
  2477.         for ( ODFacet* selectedFacet = fiter.First(); fiter.IsNotComplete();
  2478.               selectedFacet = fiter.Next() )
  2479.         {
  2480.             if ( selectedFacet->IsSelected(ev) )
  2481.             {
  2482.                 facet = selectedFacet;
  2483.                 break;
  2484.             }
  2485.         }
  2486.     }
  2487.     
  2488.     // If there are no active facets anywhere, this method should never
  2489.     // have been called, so signal an error.
  2490.     if ( facet == kODNULL )
  2491.         THROW(kODErrInvalidFrame);
  2492.         
  2493.     return facet;
  2494. }
  2495.  
  2496. //------------------------------------------------------------------------------
  2497. // Method:        FacetAdded
  2498. // Origin:        ODPart
  2499. //
  2500. // Description:    This method is called when any part adds a facet to
  2501. //                one of our display frames.
  2502. //------------------------------------------------------------------------------
  2503.  
  2504. void ListPart::FacetAdded( Environment*    ev,
  2505.                              ODFacet*        facet )
  2506. {
  2507.     WeBeHere("\pListPart::FacetAdded");
  2508.     SOM_Trace("ListPart","FacetAdded");
  2509.  
  2510. // ES 11/13/95
  2511.     ListFacetInfoPtr lfip = (ListFacetInfoPtr)NewPtrClear(sizeof(ListFacetInfo));
  2512.     facet->SetPartInfo(ev, (ODInfoType)lfip);
  2513.  
  2514.     ODFrame* frame = facet->GetFrame(ev);
  2515.     CFrameInfo* frameInfo = (CFrameInfo*) frame->GetPartInfo(ev);
  2516.  
  2517. // ES 11/15/95
  2518.     ODShape* requestedFrameShape = frame->AcquireFrameShape(ev, kODNULL);
  2519.     ODRect odrct;
  2520.     Rect rct;
  2521.     requestedFrameShape->GetBoundingBox(ev, &odrct);
  2522.     odrct.AsQDRect(rct);
  2523.     MyAdjustRectFacet(ev, &rct);
  2524.     odrct = (rct);
  2525.     requestedFrameShape->SetRectangle(ev, &odrct);
  2526.     ODShape* newShape = frame->RequestFrameShape(ev, requestedFrameShape, kODNULL);
  2527.     newShape->Release(ev);
  2528.     requestedFrameShape->Release(ev);
  2529.         
  2530. // ES 11/14/95
  2531.     this->AdjustFacets(ev, frame);
  2532.  
  2533.     // If a root facet is being added, the frame should be activated when the
  2534.     // window is "selected". This prevents OpenDoc from getting into an
  2535.     // ambiguous state of no part having the selection focus.
  2536.  
  2537.     if ( frame->IsRoot(ev) )
  2538.     {
  2539.         frameInfo->SetActiveFacet(facet);
  2540.         frameInfo->SetFrameReactivate(kODTrue);
  2541.     }
  2542.     
  2543.     // If a frame had all of its facets removed, the frame would have
  2544.     // hidden any of its part windows. If the frame becomes visible again,
  2545.     // by having a facet added to it, we will "show" the part window for
  2546.     // the frame.
  2547.     
  2548.     if ( (CountFramesFacets(ev, frame) == 1) )
  2549.     {
  2550.         TempODWindow window = frameInfo->AcquirePartWindow(ev);
  2551.         if ( window ) window->Show(ev);
  2552.     }
  2553. }
  2554.  
  2555. //------------------------------------------------------------------------------
  2556. // Method:        FacetRemoved
  2557. // Origin:        ODPart
  2558. //
  2559. // Description:    This method is called when any part removes a facet
  2560. //                from one of our display frames.
  2561. //
  2562. //                The part just removes the "active" note from the
  2563. //                appropriate display frame if necessary since this
  2564. //                facet will not be available, nor active, again.
  2565. //------------------------------------------------------------------------------
  2566.  
  2567. void ListPart::FacetRemoved( Environment*    ev,
  2568.                                ODFacet*        facet )
  2569. {
  2570.     WeBeHere("\pListPart::FacetRemoved");
  2571.     SOM_Trace("ListPart","FacetRemoved");
  2572.  
  2573. // ES 11/13/95
  2574.     ListFacetInfoPtr lfip = (ListFacetInfoPtr)facet->GetPartInfo(ev);
  2575.     ControlHandle aCtl = lfip->fListCtl;
  2576.     if (aCtl) DisposeControl(aCtl);
  2577.     
  2578.     if (fKind == kActive)
  2579.         if (fLineOpened)
  2580.             if (facet == fOpenedFacet)
  2581.                 {
  2582.                 CloseCellOpened(ev);
  2583.  
  2584.                 CListIterator fiter(fDisplayFrames);
  2585.                 for ( CFrameProxy* proxy = (CFrameProxy*) fiter.First();
  2586.                         fiter.IsNotComplete(); proxy = (CFrameProxy*) fiter.Next() )
  2587.                     {
  2588.                     proxy->GetFrame(ev)->Invalidate(ev, kODNULL, kODNULL);
  2589.                     }
  2590.                 }
  2591.     DisposePtr((Ptr)lfip);
  2592.  
  2593.     ODFrame*    frame = facet->GetFrame(ev);
  2594.     TempODFrame    containingFrame = frame->AcquireContainingFrame(ev);
  2595.     CFrameInfo* frameInfo = (CFrameInfo*) frame->GetPartInfo(ev);
  2596.  
  2597.     // If the facet was the active facet, it can no longer be.
  2598.        if ( ODObjectsAreEqual(ev, frameInfo->GetActiveFacet(), facet) )
  2599.         frameInfo->SetActiveFacet(kODNULL);
  2600.  
  2601.     // If a frame has all of its facets removed and its containing frame set
  2602.     // to NULL, the frame becomes "hidden". If the frame owns a part window,
  2603.     // the part window should also be hidden.
  2604.     
  2605.     if ( (CountFramesFacets(ev, frame) == 0) &&
  2606.             (containingFrame == kODNULL) )
  2607.     {
  2608.         TempODWindow window = frameInfo->AcquirePartWindow(ev);
  2609.         if ( window ) window->Hide(ev);
  2610.     }
  2611. }
  2612.  
  2613. //------------------------------------------------------------------------------
  2614. // Method:        Draw
  2615. // Origin:        ODPart
  2616. //
  2617. // Description:    This method is called when a facet of a part's display
  2618. //                frame intersects the invalidated portion of an OpenDoc
  2619. //                window. The invalidShape parameter passed in is the
  2620. //                portion of the facet which has been invalidated.
  2621. //
  2622. //                The part sets up the drawing environment using a
  2623. //                C++ helper class (CFocus) and then calls the
  2624. //                appropriate drawing method based on the frame's
  2625. //                viewType.
  2626. //------------------------------------------------------------------------------
  2627.  
  2628. void ListPart::Draw( Environment*        ev,
  2629.                        ODFacet*            facet,
  2630.                        ODShape*            invalidShape )
  2631. {
  2632.     WeBeHere("\pListPart::Draw");
  2633.     SOM_Trace("ListPart","Draw");
  2634.  
  2635.     // Focus the port and origin for drawing in our facet.
  2636.     // Note that this instance of the CFocusDrawingEnv class
  2637.     // is being allocated on the stack. When the execution
  2638.     // leaves the scope of this method, the destructor (which
  2639.     // cleans up the drawing environment) is automatically
  2640.     // called.
  2641.     CFocus initiateDrawing(ev, facet, invalidShape);
  2642.     
  2643.     ODTypeToken view = facet->GetFrame(ev)->GetViewType(ev);
  2644.     
  2645.     if ( view == gGlobals->fLargeIconView || view == gGlobals->fSmallIconView )
  2646.         this->DrawIconView(ev, facet);
  2647.     else if ( view == gGlobals->fThumbnailView )
  2648.         this->DrawThumbnailView(ev, facet);
  2649.     else
  2650.         this->DrawFrameView(ev, facet);
  2651. }
  2652.  
  2653. //------------------------------------------------------------------------------
  2654. // Method:        DrawFrameView
  2655. // Origin:        ListPart
  2656. //
  2657. // Description:    This method is called by the part when the frame being drawn is
  2658. //                in "frame" view.
  2659. //
  2660. //                ListPart really has not intrisic content. However, to provide
  2661. //                some visual display, we draw the class name at 80% of the
  2662. //                frame's current height using an bold font.
  2663. //------------------------------------------------------------------------------
  2664.  
  2665. void ListPart::DrawFrameView( Environment*    ev,
  2666.                                 ODFacet*        facet )
  2667. {
  2668.     WeBeHere("\pListPart::DrawFrameView");
  2669.     SOM_Trace("ListPart","DrawFrameView");
  2670.  
  2671.     ODBoolean printing = kODFalse;
  2672.     if ( facet->GetCanvas(ev)->HasPlatformPrintJob(ev, kODQuickDraw) ) printing = kODTrue;
  2673.     else if ( facet->GetCanvas(ev)->HasPlatformPrintJob(ev, kODQuickDrawGX) ) printing = kODTrue;
  2674.  
  2675. // ES 11/13/95
  2676.     ListFacetInfoPtr lfip = (ListFacetInfoPtr)facet->GetPartInfo(ev);
  2677.     Rect rct = lfip->fUsedRect;
  2678.     ODFrame*    frame = facet->GetFrame(ev);
  2679.  
  2680.     RgnHandle    oldClip = NULL;
  2681.     RgnHandle    newClip;
  2682.  
  2683. // ES 11/16/95
  2684.     if (frame->IsRoot(ev))
  2685.     {
  2686.         GrafPtr    curPort;
  2687.         ::GetPort(&curPort);
  2688.         Rect r = curPort->portRect;
  2689.         r.left = r.right  - 15;
  2690.         r.top  = r.bottom - 15;
  2691.         ::GetClip(oldClip = NewRgn());
  2692.         ::ClipRect(&r);
  2693.         ::DrawGrowIcon(curPort);
  2694.         ::GetClip(newClip = ::NewRgn());
  2695.         ::DiffRgn(oldClip, newClip, newClip);
  2696.         ::SetClip(newClip);
  2697.         ::DisposeRgn(newClip);
  2698.         ::EraseRect(&(curPort->portRect));
  2699.     }
  2700.  
  2701.     if (!printing)
  2702.         {
  2703.         GrafPtr    curPort;
  2704.         ::GetPort(&curPort);
  2705.         Rect r = curPort->portRect;
  2706.         short dh = -r.left;
  2707.         short dv = -r.top;
  2708.         SetOrigin(0, 0);
  2709.         OffsetRgn(curPort->clipRgn, dh, dv);
  2710.         
  2711.         if (frame->IsRoot(ev))
  2712.             {
  2713.             if ((rct.top-1+dv != (*(lfip->fListCtl))->contrlRect.top) || (rct.right+1+dh != (*(lfip->fListCtl))->contrlRect.right))
  2714.                 {
  2715.                 Rect theRect = (*(lfip->fListCtl))->contrlRect;
  2716.                 ::HideControl(lfip->fListCtl);
  2717.                 ::MoveControl(lfip->fListCtl, rct.right-15+dh, rct.top-1+dv);
  2718.                 }
  2719.             }
  2720.         else if ((rct.top+dv != (*(lfip->fListCtl))->contrlRect.top) || (rct.right+dh != (*(lfip->fListCtl))->contrlRect.right))
  2721.             {
  2722.             Rect theRect = (*(lfip->fListCtl))->contrlRect;
  2723.             ::HideControl(lfip->fListCtl);
  2724.             ::MoveControl(lfip->fListCtl, rct.right-16+dh, rct.top+dv);
  2725.             }
  2726.     
  2727.         if ((*(lfip->fListCtl))->contrlVis == 0) ::ShowControl(lfip->fListCtl);
  2728.         else ::Draw1Control(lfip->fListCtl);
  2729.     
  2730.         OffsetRgn(curPort->clipRgn, -dh, -dv);
  2731.         SetOrigin(-dh, -dv);
  2732.         }
  2733.  
  2734.     if (!printing)
  2735.         {
  2736.         // draw the list, and capture the image for thumbnail display
  2737.         if (fThumbnail)
  2738.             ::KillPicture((PicHandle)fThumbnail);
  2739.         fThumbnail = NULL;
  2740.         fThumbnail = (Handle)::OpenPicture(&rct);
  2741.         }
  2742.  
  2743.     if (!(frame->IsRoot(ev))) FrameRect(&rct);
  2744.     CopyFromGWorld(ev, facet);
  2745.  
  2746.     if (!printing)
  2747.         {
  2748.         ::ClosePicture();
  2749.         ::DrawPicture((PicHandle)fThumbnail, &rct);
  2750.         }
  2751.     
  2752. // ES 11/16/95
  2753.     if (oldClip) {
  2754.         ::SetClip(oldClip);
  2755.         ::DisposeRgn(oldClip);
  2756.     }
  2757. }
  2758.  
  2759. //------------------------------------------------------------------------------
  2760. // Method:        DrawIconView
  2761. // Origin:        ListPart
  2762. //
  2763. // Description:    This method is called by the part when the frame being
  2764. //                drawn is in "standard icon" view.
  2765. //
  2766. //                The part uses the Icon Utilities toolbox manager to
  2767. //                aid in drawing icons in active windows. The Guidelines
  2768. //                require a different appearance for selected icons in
  2769. //                inactive windows, which we do manually.
  2770. //------------------------------------------------------------------------------
  2771.  
  2772. void ListPart::DrawIconView( Environment*        ev,
  2773.                                ODFacet*            facet )
  2774. {
  2775.     SOM_Trace("ListPart","DrawIconView");
  2776.  
  2777.     Rect                iconRect;
  2778.     IconTransformType     transformType = ttNone;
  2779.     CFrameInfo*            frameInfo;
  2780.     ODFrame*            frame; 
  2781.     ODTypeToken            viewType;
  2782.     
  2783.     frame        = facet->GetFrame(ev);
  2784.     viewType    = frame->GetViewType(ev);
  2785.     frameInfo     = (CFrameInfo*) frame->GetPartInfo(ev);
  2786.     
  2787.     // Check to see if the facet is selected
  2788.     if ( facet->GetHighlight(ev) == kODFullHighlight )
  2789.         transformType = ttSelected;
  2790.     
  2791.     // Check to see if the frame has been opened into a part window.
  2792.     TempODWindow window = frameInfo->AcquirePartWindow(ev);
  2793.     if ( window && window->IsShown(ev) )
  2794.         transformType |= ttOpen;
  2795.     
  2796.     // Draw the icon.
  2797.     if ( viewType == gGlobals->fLargeIconView )
  2798.         SetRect(&iconRect, 0, 0, kODLargeIconSize, kODLargeIconSize);
  2799.     else // ( viewType == gGlobals->fSmallIconView )
  2800.         SetRect(&iconRect, 0, 0, kODSmallIconSize, kODSmallIconSize);
  2801.  
  2802.     CUsingLibraryResources res;
  2803.     PlotIconID(&iconRect, atAbsoluteCenter, transformType, kBaseResourceID);
  2804. }
  2805.  
  2806. //------------------------------------------------------------------------------
  2807. // Method:        DrawThumbnailView
  2808. // Origin:        ListPart
  2809. //
  2810. // Description:    This method is called by the part when the frame being
  2811. //                drawn is in "thumbnail" view.
  2812. //
  2813. //                The part uses a picture for its thumbnail view because
  2814. //                it has no intrinsic content. A picture resource is
  2815. //                probably not sufficient for parts with real content.
  2816. //------------------------------------------------------------------------------
  2817.  
  2818. void ListPart::DrawThumbnailView( Environment*    ev,
  2819.                                     ODFacet*        /*facet*/ )
  2820. {
  2821.     WeBeHere("\pListPart::DrawThumbnailView");
  2822.     SOM_Trace("ListPart","DrawThumbnailView");
  2823.  
  2824. // ES 11/15/95
  2825.     if (!fThumbnail)
  2826.         LoadThumbnail(ev, fsomSelf, &fThumbnail);
  2827.     
  2828. // ES 11/15/95
  2829. //    Rect bounds = (**(PicHandle) fThumbnail).picFrame;
  2830. //    OffsetRect(&bounds, -bounds.left, -bounds.top);
  2831.  
  2832.     Rect bounds;
  2833.     SetRect(&bounds, 0, 0, 100, 100);
  2834.     DrawPicture((PicHandle) fThumbnail, &bounds);
  2835. }
  2836.  
  2837. //------------------------------------------------------------------------------
  2838. // Method:        GeometryChanged
  2839. // Origin:        ODPart
  2840. //
  2841. // Description:    This method is called when the ExternalTransform or
  2842. //                ClipShape of a facet on one this part's display frames
  2843. //                changes.
  2844. //------------------------------------------------------------------------------
  2845.  
  2846. void ListPart::GeometryChanged( Environment*    ev,
  2847.                                   ODFacet*        facet,
  2848.                                   ODBoolean        clipShapeChanged,
  2849.                                   ODBoolean        /*externalTransformChanged*/ )
  2850. {
  2851.     SOM_Trace("ListPart","GeometryChanged");
  2852.  
  2853.     if ( clipShapeChanged )
  2854.         // Specifying kODNULL means to invalidate the clipShape (which was
  2855.         // calculated from the usedShape).
  2856.         facet->Invalidate(ev, kODNULL, kODNULL);
  2857. }
  2858.  
  2859. //------------------------------------------------------------------------------
  2860. // Method:        HighlightChanged
  2861. // Origin:        ODPart
  2862. //
  2863. // Description:    This method is called when a facet....
  2864. //------------------------------------------------------------------------------
  2865.  
  2866. void ListPart::HighlightChanged(Environment* ev, ODFacet* facet)
  2867. {
  2868.     ODFrame* frame = facet->GetFrame(ev);
  2869.     
  2870.     // The frame view has no "special" drawing characteristics
  2871.     // when opened or selected, so we don't need to update our
  2872.     // content.
  2873.     
  2874.     if ( frame->GetViewType(ev) != gGlobals->fFrameView )
  2875.         frame->Invalidate(ev, kODNULL, kODNULL);
  2876. }
  2877.  
  2878. //------------------------------------------------------------------------------
  2879. // Method:        BeginRelinquishFocus
  2880. // Origin:        ODPart
  2881. //
  2882. // Description:    This method is called when another part (or possibly
  2883. //                ourself) is requesting a focus for one of its display
  2884. //                frames. Returning true means we are willing to give
  2885. //                up the requested focus.
  2886. //
  2887. //                The part willingly gives up any focus unless it is the
  2888. //                modal focus which we don't want to give up until we
  2889. //                are completely done displaying a modal dialog.
  2890. //------------------------------------------------------------------------------
  2891.  
  2892. ODBoolean ListPart::BeginRelinquishFocus( Environment*    ev,
  2893.                                             ODTypeToken        focus,
  2894.                                             ODFrame*        /*ownerFrame*/,
  2895.                                             ODFrame*        proposedFrame )
  2896. {
  2897.     WeBeHere("\pListPart::BeginRelinquishFocus");
  2898.     SOM_Trace("ListPart","BeginRelinquishFocus");
  2899.  
  2900.     ODBoolean willRelinquish = kODTrue;
  2901.  
  2902.     // Another part is trying to put up a Modal dialog while we
  2903.     // are currently displaying ours. Deny the request.
  2904.     if ( focus == gGlobals->fModalFocus )
  2905.     {
  2906.         TempODPart proposedPart = ODAcquirePart(ev,proposedFrame);
  2907.         if ( ODObjectsAreEqual(ev, proposedPart, fSelf) == kODFalse )
  2908.             willRelinquish = kODFalse;
  2909.     }
  2910.                 
  2911.     return willRelinquish;
  2912. }
  2913.  
  2914. //------------------------------------------------------------------------------
  2915. // Method:        CommitRelinquishFocus
  2916. // Origin:        ODPart
  2917. //
  2918. // Description:    This method is called when it is actually time to give
  2919. //                up a focus that had been requested by another part (or
  2920. //                possibly ourself).
  2921. //
  2922. //                The part calls its FocusLost method to handle the 
  2923. //                "reliquishing" of the particular focus.
  2924. //------------------------------------------------------------------------------
  2925.  
  2926. void ListPart::CommitRelinquishFocus( Environment*    ev,
  2927.                                         ODTypeToken        focus,
  2928.                                         ODFrame*        ownerFrame,
  2929.                                         ODFrame*        /*proposedFrame*/ )
  2930. {
  2931.     WeBeHere("\pListPart::CommitRelinquishFocus");
  2932.     SOM_Trace("ListPart","CommitRelinquishFocus");
  2933.  
  2934.     // We agreed to give up our FocusSet and now we are being asked to
  2935.     // do so.
  2936.     this->FocusLost(ev, focus, ownerFrame);
  2937. }
  2938.  
  2939. //------------------------------------------------------------------------------
  2940. // Method:        AbortRelinquishFocus
  2941. // Origin:        ODPart
  2942. //
  2943. // Description:    This method is called when another part (or possibly
  2944. //                ourself) requested a focus for one of its display
  2945. //                frames, but we returned kODFalse from
  2946. //                BeginRelinqishFocus for one, or all, of the requested
  2947. //                focus. At this point, we are being told to resume
  2948. //                ownership of the focus.
  2949. //------------------------------------------------------------------------------
  2950.  
  2951. void ListPart::AbortRelinquishFocus( Environment*        ev,
  2952.                                        ODTypeToken        /*focus*/,
  2953.                                        ODFrame*            /*ownerFrame*/,
  2954.                                        ODFrame*            /*proposedFrame*/ )
  2955. {
  2956.     WeBeHere("\pListPart::AbortRelinquishFocus");
  2957.     SOM_Trace("ListPart","AbortRelinquishFocus");
  2958.  
  2959.     // Some parts may have suspended some events in the BeginRelinquishFocus
  2960.     // method. If so, they would resume those events here.
  2961. }
  2962.  
  2963. //------------------------------------------------------------------------------
  2964. // Method:        FocusAcquired
  2965. // Origin:        ODPart
  2966. //
  2967. // Description:    This method is called when the Arbitrator has
  2968. //                registered us as the "owner" of the particular focus.
  2969. //                This can occur if we are explicitly assigned a focus, or if a
  2970. //                focus is transfered to one of the part's display frames.
  2971. //
  2972. //                The part will request its complete focus set to become "active".
  2973. //                If the part is successful, we notify ourself to become active.
  2974. //------------------------------------------------------------------------------
  2975.  
  2976. void ListPart::FocusAcquired( Environment*    ev,
  2977.                                 ODTypeToken        focus,
  2978.                                 ODFrame*        ownerFrame )
  2979. {
  2980.     WeBeHere("\pListPart::FocusAcquired");
  2981.     SOM_Trace("ListPart","FocusAcquired");
  2982.  
  2983.     ODArbitrator* arbitrator =  ODGetSession(ev,fSelf)->GetArbitrator(ev);
  2984.  
  2985.     if ( arbitrator->RequestFocusSet(ev, gGlobals->fUIFocusSet, ownerFrame) )
  2986.     {
  2987.         this->PartActivated(ev, ownerFrame);
  2988.  
  2989.         fFocusedFacet = GetActiveFacetForFrame(ev, ownerFrame);
  2990.     }
  2991. }
  2992.  
  2993. //------------------------------------------------------------------------------
  2994. // Method:        FocusLost
  2995. // Origin:        ODPart
  2996. //
  2997. // Description:    This method is called when the Arbitrator has
  2998. //                unregistered us as the "owner" of the particular
  2999. //                focus.
  3000. //
  3001. //                The part unmarks the active frame if the selection
  3002. //                focus is lost.
  3003. //------------------------------------------------------------------------------
  3004.  
  3005. void ListPart::FocusLost( Environment*    ev,
  3006.                             ODTypeToken        focus,
  3007.                             ODFrame*        ownerFrame )
  3008. {
  3009.     WeBeHere("\pListPart::FocusLost");
  3010.     SOM_Trace("ListPart","FocusLost");
  3011.  
  3012.     if ( focus == gGlobals->fSelectionFocus )
  3013.     {
  3014. // ES 11/13/95
  3015.         fFocusedFacet = kODNULL;
  3016.         if (fKind == kActive) if (fLineOpened) CloseCellOpened(ev);
  3017.  
  3018.         CFrameInfo* frameInfo = (CFrameInfo*) ownerFrame->GetPartInfo(ev);
  3019.         frameInfo->SetFrameActive(kODFalse);
  3020.     }
  3021. }
  3022.  
  3023. //------------------------------------------------------------------------------
  3024. // Method:        RelinquishAllFoci
  3025. // Origin:        ListPart
  3026. //
  3027. // Description:    This method is called when a frame is going away. The method
  3028. //                relinquishes all foci the frame owns.
  3029. //------------------------------------------------------------------------------
  3030.  
  3031. void ListPart::RelinquishAllFoci( Environment*    ev,
  3032.                                     ODFrame*        frame )
  3033. {
  3034.     WeBeHere("\pListPart::RelinquishAllFoci");
  3035.     SOM_Trace("ListPart","RelinquishAllFoci");
  3036.  
  3037.     ODArbitrator* arbitrator = ODGetSession(ev,fSelf)->GetArbitrator(ev);
  3038.     
  3039.     TRY
  3040.         TempODFrame focusFrame = arbitrator->AcquireFocusOwner(ev, gGlobals->fSelectionFocus);
  3041.         if ( ODObjectsAreEqual(ev, focusFrame, frame) )
  3042.         {
  3043.             arbitrator->RelinquishFocus(ev, gGlobals->fSelectionFocus, frame);
  3044.             this->FocusLost(ev, gGlobals->fSelectionFocus, frame);
  3045.         }
  3046.     CATCH_ALL
  3047.     ENDTRY
  3048.  
  3049.     TRY
  3050.         TempODFrame focusFrame = arbitrator->AcquireFocusOwner(ev, gGlobals->fMenuFocus);
  3051.         if ( ODObjectsAreEqual(ev, focusFrame, frame) )
  3052.         {
  3053.             arbitrator->RelinquishFocus(ev, gGlobals->fMenuFocus, frame);
  3054.             this->FocusLost(ev, gGlobals->fMenuFocus, frame);
  3055.         }
  3056.     CATCH_ALL
  3057.     ENDTRY
  3058.  
  3059.     TRY
  3060.         TempODFrame focusFrame = arbitrator->AcquireFocusOwner(ev, gGlobals->fKeyFocus);
  3061.         if ( ODObjectsAreEqual(ev, focusFrame, frame) )
  3062.         {
  3063.             arbitrator->RelinquishFocus(ev, gGlobals->fKeyFocus, frame);
  3064.             this->FocusLost(ev, gGlobals->fKeyFocus, frame);
  3065.         }
  3066.     CATCH_ALL
  3067.     ENDTRY
  3068.  
  3069.     TRY
  3070.         TempODFrame focusFrame = arbitrator->AcquireFocusOwner(ev, gGlobals->fScrollFocus);
  3071.         if ( ODObjectsAreEqual(ev, focusFrame, frame) )
  3072.         {
  3073.             arbitrator->RelinquishFocus(ev, gGlobals->fScrollFocus, frame);
  3074.             this->FocusLost(ev, gGlobals->fScrollFocus, frame);
  3075.         }
  3076.     CATCH_ALL
  3077.     ENDTRY
  3078. }
  3079.  
  3080. //------------------------------------------------------------------------------
  3081. // Method:        PartActivated
  3082. // Origin:        ListPart
  3083. //
  3084. // Description:    This method is called when the part has successfully acquired
  3085. //                the set of foci which allow it to "run".
  3086. //------------------------------------------------------------------------------
  3087.  
  3088. void ListPart::PartActivated( Environment*    ev,
  3089.                                 ODFrame*        frame )
  3090. {
  3091.     WeBeHere("\pListPart::PartActivated");
  3092.     SOM_Trace("ListPart","PartActivated");
  3093.     
  3094.     // We are required to re-validate the menubar before displaying it because
  3095.     // any part can/could swap the base menubar at any time.
  3096.     if ( gGlobals->fMenuBar->IsValid(ev) == kODFalse )
  3097.     {
  3098.         ODReleaseObject(ev, gGlobals->fMenuBar);
  3099.         gGlobals->fMenuBar = ODGetSession(ev,fSelf)->GetWindowState(ev)->CopyBaseMenuBar(ev);
  3100.         
  3101.         // After copying the "new" base menu bar, don't forget to re-install
  3102.         // your part's menus.
  3103.     }
  3104.         
  3105.     // Display our menu bar.
  3106.     gGlobals->fMenuBar->Display(ev);
  3107.     
  3108.     // And set our "active" state.
  3109.     CFrameInfo* frameInfo = (CFrameInfo*) frame->GetPartInfo(ev);
  3110.     frameInfo->SetFrameActive(kODTrue);
  3111. }
  3112.  
  3113. //------------------------------------------------------------------------------
  3114. // Method:        ActivateFrame
  3115. // Origin:        ListPart
  3116. //
  3117. // Description:    This method is called by the part when a kODEvtMouseUp
  3118. //                occurs in an inactive frame in an active window, and
  3119. //                when an OpenDoc document comes forward.
  3120. //
  3121. //                The part activates the frame by requesting the
  3122. //                UIFocusSet (created in Initialize) and by calling
  3123. //                FocusAcquired if we were successful. The method
  3124. //                returns true if no problems were encountered as a
  3125. //                signal to the caller that the frame is now "active".
  3126. //------------------------------------------------------------------------------
  3127.  
  3128. ODBoolean ListPart::ActivateFrame( Environment*    ev,
  3129.                                      ODFrame*        frame, ODFacet* facet )
  3130. {
  3131.     WeBeHere("\pListPart::ActivateFrame");
  3132.     SOM_Trace("ListPart","ActivateFrame");
  3133.  
  3134.     ODBoolean activated = kODFalse;
  3135.  
  3136.     // Request the set of foci necessary to become active.
  3137.     if ( ODGetSession(ev,fSelf)->GetArbitrator(ev)->RequestFocusSet(ev, gGlobals->fUIFocusSet, frame) )
  3138.     {
  3139.         fFocusedFacet = facet;
  3140.  
  3141.         // Activate the part.
  3142.         this->PartActivated(ev, frame);
  3143.         // We were able to become active.
  3144.         activated = kODTrue;
  3145.     }
  3146.  
  3147.     // Let our caller know we succeded or failed.
  3148.     return activated;
  3149. }
  3150.  
  3151. //------------------------------------------------------------------------------
  3152. // Method:        WindowActivating
  3153. // Origin:        ListPart
  3154. //
  3155. // Description:    This method is called by the part when a window activation
  3156. //                event (kODEvtActivate) occurs.
  3157. //
  3158. //                The part remembers the frame's active state and restores it when
  3159. //                events come in. If the frame is active and the window is being
  3160. //                sent into the background, remember to reactivate the part when
  3161. //                the window is reactivated.
  3162. //------------------------------------------------------------------------------
  3163.  
  3164. void ListPart::WindowActivating( Environment*        ev,
  3165.                                    ODFrame*            frame,
  3166.                                    ODBoolean        activating,
  3167.                                    ODFacet* facet )
  3168. {
  3169.     WeBeHere("\pListPart::WindowActivating");
  3170.     SOM_Trace("ListPart","WindowActivating");
  3171.  
  3172.     CFrameInfo* frameInfo = (CFrameInfo*) frame->GetPartInfo(ev);
  3173.     
  3174.     // The window is being activated and we had the selection focus when
  3175.     // the window was deactivated, so activate ourself.
  3176.     if ( activating && frameInfo->FrameNeedsReactivating() )
  3177.     {
  3178.         this->ActivateFrame(ev, frame, facet);
  3179.         frameInfo->SetFrameReactivate(kODFalse);
  3180.     }
  3181.     // The window is being deactivated and we are the active part.
  3182.     // Give up our foci and remind ourselves that we need to request
  3183.     // the focus when the window is reactivated.
  3184.     else if ( !activating && frameInfo->IsFrameActive() )
  3185.     {
  3186.         frameInfo->SetFrameReactivate(kODTrue);
  3187.     }
  3188. }
  3189.  
  3190. //------------------------------------------------------------------------------
  3191. // Method:        HandleEvent
  3192. // Origin:        ODPart
  3193. //
  3194. // Description:    The method is called when an event, which falls into
  3195. //                the category of an owned focus, occurs. The two
  3196. //                exceptions to this are "mouse movement" events and 
  3197. //                embedded frame events, which can occur when a part
  3198. //                owns no foci.
  3199. //
  3200. //                The part returns true if the event was handled.
  3201. //------------------------------------------------------------------------------
  3202.  
  3203.  
  3204. ODBoolean ListPart::HandleEvent( Environment*        ev,
  3205.                                    ODEventData*        event,
  3206.                                    ODFrame*            frame,
  3207.                                    ODFacet*            facet,
  3208.                                    ODEventInfo*        eventInfo )
  3209. {
  3210.     WeBeHere("\pListPart::HandleEvent");
  3211.     SOM_Trace("ListPart","HandleEvent");
  3212.  
  3213.     ODBoolean    eventHandled = kODFalse;
  3214.  
  3215.     // Event handling is basically the same as standard Macintosh applications,
  3216.     // except that the events have been renamed for cross-platform compatability.
  3217.     
  3218.     switch ( event->what )
  3219.     {
  3220.         case kODEvtMouseDown:
  3221.         case kODEvtMouseUp:
  3222.             eventHandled = this->HandleMouseEvent(ev, event, facet, eventInfo);
  3223.             break;
  3224.             
  3225.         case kODEvtMenu:
  3226.             eventHandled = this->HandleMenuEvent(ev, event, frame);
  3227.             break;
  3228.  
  3229.         case kODEvtActivate:
  3230.             // We are being notified that a window we are displayed in has
  3231.             // just been de/activated (un/hilighted).
  3232. // ES 11/16/95
  3233.             if (facet) if (facet->GetFrame(ev)->GetViewType(ev) == gGlobals->fFrameView)
  3234.                 {
  3235.                 CFocus foc(ev, facet);
  3236.                 ListFacetInfoPtr lfip = (ListFacetInfoPtr)facet->GetPartInfo(ev);
  3237.         GrafPtr    curPort;
  3238.         ::GetPort(&curPort);
  3239.         Rect r = curPort->portRect;
  3240.         short dh = -r.left;
  3241.         short dv = -r.top;
  3242.         SetOrigin(0, 0);
  3243.         OffsetRgn(curPort->clipRgn, dh, dv);
  3244.  
  3245.                 if (lfip) ::HiliteControl(lfip->fListCtl, ((event->modifiers & 1) == 0)?254:0);
  3246.  
  3247.         OffsetRgn(curPort->clipRgn, -dh, -dv);
  3248.         SetOrigin(-dh, -dv);
  3249.                 }
  3250.  
  3251.             this->WindowActivating(ev, frame, (event->modifiers & activeFlag), facet);
  3252.             eventHandled = kODTrue;
  3253.             break;
  3254.     
  3255.         case kODEvtMouseEnter:
  3256.         case kODEvtMouseLeave:
  3257.             SetCursor(&ODQDGlobals.arrow);
  3258.             eventHandled = kODTrue;
  3259.             break;
  3260.  
  3261.         case kODEvtMouseWithin:
  3262.             eventHandled = kODTrue;
  3263.             break;
  3264.  
  3265.         // Other events a part might handle
  3266.         case kODEvtKeyDown:
  3267.         case kODEvtAutoKey:
  3268.             eventHandled = kODFalse;
  3269.             if (!(event->modifiers & cmdKey))
  3270.                 {
  3271.                 if (fKind == kActive)
  3272.                     if (fLineOpened)
  3273.                         if (fsomSelf->KeyInActive(ev, fOpenedFacet, event)) eventHandled = kODTrue;
  3274.                 if (!eventHandled)
  3275.                     if (fFocusedFacet)
  3276.                         if (KeyInList(ev, event->message & charCodeMask)) eventHandled = kODTrue;
  3277.                 }
  3278.             break;
  3279.         case kODEvtNull:
  3280.             if (fKind == kActive)
  3281.                 if (fLineOpened)
  3282.                     fsomSelf->IdleOpened(ev, fOpenedFacet);
  3283.             eventHandled = kODTrue;
  3284.             break;
  3285.         case kODEvtOS:
  3286. // ES 11/16/95
  3287.             if (facet) if (facet->GetFrame(ev)->GetViewType(ev) == gGlobals->fFrameView)
  3288.                 {
  3289.                 CFocus foc(ev, facet);
  3290.                 ListFacetInfoPtr lfip = (ListFacetInfoPtr)facet->GetPartInfo(ev);
  3291.  
  3292.         GrafPtr    curPort;
  3293.         ::GetPort(&curPort);
  3294.         Rect r = curPort->portRect;
  3295.         short dh = -r.left;
  3296.         short dv = -r.top;
  3297.         SetOrigin(0, 0);
  3298.         OffsetRgn(curPort->clipRgn, dh, dv);
  3299.  
  3300.                 if (lfip) ::HiliteControl(lfip->fListCtl, ((event->modifiers & 1) == 0)?254:0);
  3301.  
  3302.         OffsetRgn(curPort->clipRgn, -dh, -dv);
  3303.         SetOrigin(-dh, -dv);
  3304.                 }
  3305.             break;
  3306.         case kODEvtMouseDownEmbedded:
  3307.         case kODEvtMouseUpEmbedded:
  3308.         case kODEvtMouseDownBorder:
  3309.         case kODEvtMouseUpBorder:
  3310.         case kODEvtWindow:
  3311.         case kODEvtKeyUp:
  3312.         case kODEvtDisk:
  3313.         
  3314.         default:
  3315.             break;
  3316.     }
  3317.  
  3318.     return eventHandled;
  3319. }
  3320.  
  3321. //------------------------------------------------------------------------------
  3322. // Method:        AdjustMenus
  3323. // Origin:        ODPart
  3324. //
  3325. // Description:    This method is called when a kODEvtMouseDown event occurs in the
  3326. //                menubar and the part owns the "menu" focus, or when the part is
  3327. //                root part of a document.
  3328. //
  3329. //                The part first verifies that the base menubar has not been
  3330. //                modified, then enables the menu items and changes their names
  3331. //                where appropriate (eg. About ListPart...).
  3332. //------------------------------------------------------------------------------
  3333.  
  3334. void ListPart::AdjustMenus( Environment*    ev,
  3335.                               ODFrame*        frame )
  3336. {
  3337.     SOM_Trace("ListPart","AdjustMenus");
  3338.  
  3339.     // The menubar object always calls the root part's AdjustMenus method before
  3340.     // calling the menu focus owner's. Because of this, we need to validate the
  3341.     // menubar in the case where we are the root part.
  3342.     if ( frame->IsRoot(ev) )
  3343.     {
  3344.         // We are required to re-validate the menubar before displaying it because
  3345.         // any part can/could swap the base menubar at any time.
  3346.         if ( gGlobals->fMenuBar->IsValid(ev) == kODFalse )
  3347.         {
  3348.             ODReleaseObject(ev, gGlobals->fMenuBar);
  3349.             gGlobals->fMenuBar = ODGetSession(ev,fSelf)->GetWindowState(ev)->CopyBaseMenuBar(ev);
  3350.             
  3351.             // After copying the "new" base menu bar, don't forget to re-install
  3352.             // your part's menus.
  3353.         }
  3354.     }        
  3355.  
  3356.     // Enable the "View As Window" command always.
  3357.     gGlobals->fMenuBar->EnableCommand(ev, kODCommandViewAsWin, !frame->IsRoot(ev));
  3358.     
  3359.     TRY
  3360.         ODArbitrator* arbitrator = ODGetSession(ev,fSelf)->GetArbitrator(ev);
  3361.         TempODFrame menuOwner = arbitrator->AcquireFocusOwner(ev, gGlobals->fMenuFocus);
  3362.     
  3363.         // There is no need to load a resource, create an ODIText object, set the menubar,
  3364.         // and cleanup, if we don't own the menu focus.
  3365.         if ( ODObjectsAreEqual(ev, frame, menuOwner) )
  3366.         {
  3367.             Str63 text;
  3368. // ES 11/24/95
  3369.             ODSLong savedRef = fsomSelf->OverrideBeginUsingLibraryResources(ev);
  3370.             Handle h = Get1Resource('STR#', kMenuStringResID);
  3371.             GetIndString(text, kMenuStringResID, kAboutTextID);
  3372.             ReleaseResource(h);
  3373.             fsomSelf->OverrideEndUsingLibraryResources(ev, savedRef);
  3374.  
  3375.             // Create an IText object to pass into the menubar.
  3376.             TempODIText    menuItem(CreateIText(gGlobals->fEditorsScript, gGlobals->fEditorsLanguage,
  3377.                                     (StringPtr)&text));
  3378.             // Change the "About" menu item text for our part.
  3379.             gGlobals->fMenuBar->SetItemString(ev, kODCommandAbout, menuItem);
  3380.         }
  3381.     CATCH_ALL
  3382.         // consume exception
  3383.     ENDTRY
  3384. }
  3385.  
  3386. //------------------------------------------------------------------------------
  3387. // Method:        HandleMenuEvent
  3388. // Origin:        ListPart
  3389. //
  3390. // Description:    This method is called by the part when a menu event is
  3391. //                received.
  3392. //
  3393. //                Using the menu bar object, we determine what the menu
  3394. //                command is, and call the appropriate method to handle
  3395. //                it.
  3396. //------------------------------------------------------------------------------
  3397.  
  3398. ODBoolean ListPart::HandleMenuEvent( Environment*        ev,
  3399.                                        ODEventData*        event,
  3400.                                        ODFrame*            frame )
  3401. {
  3402.     SOM_Trace("ListPart","HandleMenuEvent");
  3403.  
  3404.     ODULong        menuResult    = event->message;
  3405.     ODUShort    menu        = HiWord(menuResult);
  3406.     ODUShort    item        = LoWord(menuResult);
  3407.  
  3408.     switch ( gGlobals->fMenuBar->GetCommand(ev, menu, item) )
  3409.     {
  3410.         case kODCommandAbout:    
  3411.             this->DoDialogBox(ev, frame, kAboutBoxID);
  3412.             break;
  3413.  
  3414.         case kODCommandViewAsWin:
  3415.             this->Open(ev, frame);
  3416.             break;
  3417.  
  3418.         // Other commands a part might handle
  3419.         case kODCommandOpen:
  3420.         case kODCommandInsert:
  3421.         case kODCommandPageSetup:
  3422.         case kODCommandPrint:
  3423.         case kODCommandUndo:
  3424.         case kODCommandRedo:
  3425.         case kODCommandCut:
  3426.         case kODCommandCopy:
  3427.         case kODCommandPaste:
  3428.         case kODCommandPasteAs:
  3429.         case kODCommandClear:
  3430.         case kODCommandSelectAll:
  3431.         case kODCommandGetPartInfo:
  3432.         case kODCommandPreferences:
  3433.  
  3434.         default:
  3435.             return kODFalse;
  3436.     }
  3437.         
  3438.     return kODTrue;
  3439. }
  3440.  
  3441. //------------------------------------------------------------------------------
  3442. // Method:        HandleMouseEvent
  3443. // Origin:        ListPart
  3444. //
  3445. // Description:    This method is called by the part when a mouse event
  3446. //                is recieved.
  3447. //
  3448. //                A typical part would determine the event type(up/down)
  3449. //                and respond appropriately, but we have no "real"
  3450. //                content model, so we activate the part as appropriate
  3451. //                and call a generic method to handle the event.
  3452. //
  3453. // Remember:    When a frame is inactive, the first mouse up event
  3454. //                should activate it; inactive frames do not recieve
  3455. //                kODEvtMouseDown events.
  3456. //------------------------------------------------------------------------------
  3457.  
  3458. ODBoolean ListPart::HandleMouseEvent( Environment*    ev,
  3459.                                         ODEventData*    event,
  3460.                                         ODFacet*        facet,
  3461.                                         ODEventInfo*    eventInfo )
  3462. {
  3463.     SOM_Trace("ListPart","HandleMouseEvent");
  3464.  
  3465.     // If the facet parameter is invalid, the mouse up occurred outside the
  3466.     // bounds of a Modal window, otherwise it should be treated normally.
  3467.     
  3468.     if ( facet != kODNULL )
  3469.     {
  3470.         if ( event->what == kODEvtMouseUp )
  3471.         {
  3472.             ODWindow* window = facet->GetWindow(ev);
  3473.  
  3474.             TRY
  3475.                 // Activate inactive windows on the first mouse up event.
  3476.                 if ( !window->IsActive(ev) )
  3477.                     window->Select(ev);
  3478.             CATCH_ALL
  3479.             ENDTRY
  3480.         }
  3481.         else if ( event->what == kODEvtMouseDown )                
  3482.         {
  3483.             TRY
  3484.                 ODFrame* frame = facet->GetFrame(ev);
  3485.                 
  3486.                 // Get our state information from the PartInfo of the frame.
  3487.                 CFrameInfo* frameInfo = (CFrameInfo*) frame->GetPartInfo(ev);
  3488.                                 
  3489.                 // If this frame is not the active one, activate it by requesting
  3490.                 // the appropriate foci.
  3491.     
  3492.                 if ( !frameInfo->IsFrameActive() )
  3493.                 {
  3494.                     if ( this->ActivateFrame(ev, frame, facet) )
  3495.                         // Keep track of which facet was the last active for positioning
  3496.                         // child windows.
  3497.                         frameInfo->SetActiveFacet(facet);
  3498.                     else
  3499.                         // We were unable to acquire the necessary focus and activate it.
  3500.                         return kODFalse;
  3501.                 }
  3502.             CATCH_ALL
  3503.             ENDTRY
  3504.  
  3505.             Point where;
  3506.  
  3507.             // Get the localized mouse coordinates from the Event Info.
  3508.             where.h = FixedToInt(eventInfo->where.x);
  3509.             where.v = FixedToInt(eventInfo->where.y);
  3510.         
  3511.             // Handle the mouse down event.
  3512.             this->DoMouseEvent(ev, event, facet, &where);
  3513.         }
  3514.     }
  3515.     else
  3516.     {
  3517.         // User clicked outside the bounds of a Modal window, though we actually
  3518.         // never display one.
  3519.         
  3520.         SysBeep(1);
  3521.     }
  3522.  
  3523.     return kODTrue;
  3524. }
  3525.  
  3526. //------------------------------------------------------------------------------
  3527. // Method:        DoMouseEvent
  3528. // Origin:        ListPart
  3529. //
  3530. // Description:    This method is called by the part to handle mouse
  3531. //                events.
  3532. //------------------------------------------------------------------------------
  3533.  
  3534. void ListPart::DoMouseEvent( Environment*        ev,
  3535.                                ODEventData*        event,
  3536.                                ODFacet*            facet,
  3537.                                Point*            where )
  3538. {
  3539.     SOM_Trace("ListPart","DoMouseEvent");
  3540.     
  3541.     // If you part allows selections or a lasso tool, this is where you
  3542.     // would handle those events. This is also where you would handle
  3543.     // program controlled buttons or controls.
  3544.  
  3545. // ES 11/13/95
  3546.     HandleMouseDownInList(ev, event, facet, *where);
  3547.  
  3548. }
  3549.  
  3550. //------------------------------------------------------------------------------
  3551. // Method:        DoDialogBox
  3552. // Origin:        ListPart
  3553. //
  3554. // Description:    This method is called by the part when a dialog needs to be
  3555. //                displayed (eg. the About Box). If a valid error number is passed
  3556. //                in, an error dialog will be displayed.
  3557. //------------------------------------------------------------------------------
  3558.  
  3559. void ListPart::DoDialogBox( Environment*    ev,
  3560.                               ODFrame*        frame,
  3561.                               ODSShort        dialogID,
  3562.                               ODUShort        errorNumber )
  3563. {
  3564.     SOM_Trace("ListPart","DoDialogBox");
  3565.  
  3566.     ODFrame* focusFrame = frame;
  3567.     ODSession*    session = ODGetSession(ev,fSelf);
  3568.     
  3569.     // If the calling method does not have a frame available to it, we need to
  3570.     // locate a frame to use for requesting the modal focus. Find the first valid
  3571.     // frame in our display frames list.
  3572.     if ( focusFrame == kODNULL )
  3573.     {
  3574.         CListIterator fiter(fDisplayFrames);
  3575.         for ( CFrameProxy* proxy = (CFrameProxy*) fiter.First();
  3576.                 fiter.IsNotComplete(); proxy = (CFrameProxy*) fiter.Next() )
  3577.         {
  3578.             if ( proxy->FrameIsLoaded() )
  3579.                 focusFrame = proxy->GetFrame(ev);
  3580.             if ( focusFrame ) break;
  3581.         }
  3582.     }
  3583.     
  3584.     // Our dialog boxes are modal so we must request the Modal focus to prevent
  3585.     // multiple modal dialogs being displayed simultaneously.
  3586.     
  3587.     if ( session->GetArbitrator(ev)->RequestFocus(ev, gGlobals->fModalFocus, focusFrame) )
  3588.     {
  3589.         DialogPtr    dialog;
  3590.         ODSShort    itemHit;
  3591.  
  3592.         // Dim the frontmost document window.
  3593.         session->GetWindowState(ev)->DeactivateFrontWindows(ev);
  3594.                 
  3595.         ODSLong rfRef;
  3596.         rfRef = fsomSelf->OverrideBeginUsingLibraryResources(ev);
  3597.         {            
  3598.             dialog = GetNewDialog(dialogID, kODNULL, (WindowPtr) -1L);
  3599.             
  3600.             if ( dialog )
  3601.             {
  3602.                 if ( errorNumber > 0 )
  3603.                 {
  3604.                     Handle    itemHandle;
  3605.                     Rect    itemRect;
  3606.                     short    itemType;
  3607.                     Str255    errStr;
  3608.                     
  3609.                     GetIndString(errStr, kErrorStringResID, errorNumber);
  3610.                     GetDialogItem(dialog, kErrStrFieldID, &itemType, &itemHandle, &itemRect);
  3611.                     SetDialogItemText(itemHandle, errStr);
  3612.                     
  3613.                     // We don't need the cancel button for an error dialog.
  3614.                     HideDialogItem(dialog, cancel);
  3615.  
  3616.                     SetDialogDefaultItem(dialog, ok);
  3617.                 }
  3618.                 
  3619.                 SetCursor(&ODQDGlobals.arrow);
  3620.                 ShowWindow(dialog);
  3621.                 ModalDialog(kODNULL, &itemHit);
  3622.                 DisposeDialog(dialog);
  3623.             }
  3624.             else
  3625.             {
  3626.                 // Could not load About box dialog... something is amiss.
  3627.                 SysBeep(2);
  3628.             }
  3629.         }
  3630.         fsomSelf->OverrideEndUsingLibraryResources(ev, rfRef);
  3631.         
  3632.         // Inform the Arbitrator that we no longer require the Modal focus.
  3633.         session->GetArbitrator(ev)->RelinquishFocus(ev, gGlobals->fModalFocus, focusFrame);
  3634.         
  3635.         // Hilite the frontmost document window.
  3636.         session->GetWindowState(ev)->ActivateFrontWindows(ev);
  3637.     }
  3638.     else
  3639.         // If we can't get the modal focus, then another modal dialog is
  3640.         // already being displayed.
  3641.         SysBeep(2);
  3642. }
  3643.  
  3644.